diff options
-rw-r--r-- | include/clang/Driver/Options.td | 1 | ||||
-rw-r--r-- | lib/Driver/Tools.cpp | 38 | ||||
-rw-r--r-- | test/Driver/fast-math.c | 49 |
3 files changed, 77 insertions, 11 deletions
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index a220beaca8..aeb7e1be33 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -389,6 +389,7 @@ def ffast_math : Flag<"-ffast-math">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Enable the *frontend*'s 'fast-math' mode. This has no effect on " "optimizations, but provides a preprocessor macro __FAST_MATH__ the " "same as GCC's -ffast-math flag.">; +def fno_fast_math : Flag<"-fno-fast-math">, Group<f_Group>; def fmath_errno : Flag<"-fmath-errno">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Require math functions to indicate errors by setting errno">; def fno_math_errno : Flag<"-fno-math-errno">, Group<f_Group>; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 8619b98a68..f77d8ee6f3 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1749,25 +1749,30 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // 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_fno_fast_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 && + if (A->getOption().getID() != options::OPT_fno_fast_math && + 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_fno_fast_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 && + if (A->getOption().getID() != options::OPT_fno_fast_math && + A->getOption().getID() != options::OPT_fno_finite_math_only && A->getOption().getID() != options::OPT_fhonor_nans) CmdArgs.push_back("-menable-no-nans"); // -fmath-errno is the default on some platforms, e.g. BSD-derived OSes. bool MathErrno = getToolChain().IsMathErrnoDefault(); if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_fno_fast_math, options::OPT_fmath_errno, options::OPT_fno_math_errno)) MathErrno = A->getOption().getID() == options::OPT_fmath_errno; @@ -1780,38 +1785,46 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // madness. bool AssociativeMath = false; if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_fno_fast_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 && + if (A->getOption().getID() != options::OPT_fno_fast_math && + 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_fno_fast_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 && + if (A->getOption().getID() != options::OPT_fno_fast_math && + 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_fno_fast_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 && + if (A->getOption().getID() != options::OPT_fno_fast_math && + 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_fno_fast_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 && + if (A->getOption().getID() != options::OPT_fno_fast_math && + A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && A->getOption().getID() != options::OPT_ftrapping_math) TrappingMath = false; if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros && @@ -1821,6 +1834,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Validate and pass through -fp-contract option. if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_fno_fast_math, options::OPT_ffp_contract)) { if (A->getOption().getID() == options::OPT_ffp_contract) { StringRef Val = A->getValue(Args); @@ -1830,7 +1844,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, D.Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName() << Val; } - } else { // A is OPT_ffast_math + } else if (A->getOption().getID() == options::OPT_ffast_math) { // If fast-math is set then set the fp-contract mode to fast. CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast")); } @@ -1841,10 +1855,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // preprocessor macros. This is distinct from enabling any optimizations as // these options induce language changes which must survive serialization // and deserialization, etc. - if (Args.hasArg(options::OPT_ffast_math)) - CmdArgs.push_back("-ffast-math"); - if (Args.hasArg(options::OPT_ffinite_math_only)) - CmdArgs.push_back("-ffinite-math-only"); + if (Arg *A = Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math)) + if (A->getOption().matches(options::OPT_ffast_math)) + CmdArgs.push_back("-ffast-math"); + if (Arg *A = Args.getLastArg(options::OPT_ffinite_math_only, options::OPT_fno_fast_math)) + if (A->getOption().matches(options::OPT_ffinite_math_only)) + CmdArgs.push_back("-ffinite-math-only"); // Decide whether to use verbose asm. Verbose assembly is the default on // toolchains which have the integrated assembler on by default. diff --git a/test/Driver/fast-math.c b/test/Driver/fast-math.c index 8426f0950a..17bf6ed617 100644 --- a/test/Driver/fast-math.c +++ b/test/Driver/fast-math.c @@ -12,16 +12,46 @@ // CHECK-NO-INFS: "-cc1" // CHECK-NO-INFS: "-menable-no-infs" // +// RUN: %clang -### -fno-fast-math -fno-honor-infinities -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-FAST-MATH-NO-INFS %s +// CHECK-NO-FAST-MATH-NO-INFS: "-cc1" +// CHECK-NO-FAST-MATH-NO-INFS: "-menable-no-infs" +// +// RUN: %clang -### -fno-honor-infinities -fno-fast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-INFS-NO-FAST-MATH %s +// CHECK-NO-INFS-NO-FAST-MATH: "-cc1" +// CHECK-NO-INFS-NO-FAST-MATH-NOT: "-menable-no-infs" +// // RUN: %clang -### -fno-honor-nans -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO-NANS %s // CHECK-NO-NANS: "-cc1" // CHECK-NO-NANS: "-menable-no-nans" // +// RUN: %clang -### -fno-fast-math -fno-honor-nans -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-FAST-MATH-NO-NANS %s +// CHECK-NO-FAST-MATH-NO-NANS: "-cc1" +// CHECK-NO-FAST-MATH-NO-NANS: "-menable-no-nans" +// +// RUN: %clang -### -fno-honor-nans -fno-fast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-NANS-NO-FAST-MATH %s +// CHECK-NO-NANS-NO-FAST-MATH: "-cc1" +// CHECK-NO-NANS-NO-FAST-MATH-NOT: "-menable-no-nans" +// // RUN: %clang -### -fmath-errno -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-MATH-ERRNO %s // CHECK-MATH-ERRNO: "-cc1" // CHECK-MATH-ERRNO: "-fmath-errno" // +// RUN: %clang -### -fno-fast-math -fmath-errno -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-FAST-MATH-MATH-ERRNO %s +// CHECK-NO-FAST-MATH-MATH-ERRNO: "-cc1" +// CHECK-NO-FAST-MATH-MATH-ERRNO: "-fmath-errno" +// +// RUN: %clang -### -fmath-errno -fno-fast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-MATH-ERRNO-NO-FAST-MATH %s +// CHECK-MATH-ERRNO-NO-FAST-MATH: "-cc1" +// CHECK-MATH-ERRNO-NO-FAST-MATH-NOT: "-fmath-errno" +// // RUN: %clang -### -fmath-errno -fno-math-errno -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO-MATH-ERRNO %s // RUN: %clang -### -target i686-apple-darwin -c %s 2>&1 \ @@ -43,6 +73,18 @@ // CHECK-UNSAFE-MATH: "-cc1" // CHECK-UNSAFE-MATH: "-menable-unsafe-fp-math" // +// RUN: %clang -### -fno-fast-math -fno-math-errno -fassociative-math -freciprocal-math \ +// RUN: -fno-signed-zeros -fno-trapping-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-FAST-MATH-UNSAFE-MATH %s +// CHECK-NO-FAST-MATH-UNSAFE-MATH: "-cc1" +// CHECK-NO-FAST-MATH-UNSAFE-MATH: "-menable-unsafe-fp-math" +// +// RUN: %clang -### -fno-fast-math -fno-math-errno -fassociative-math -freciprocal-math \ +// RUN: -fno-fast-math -fno-signed-zeros -fno-trapping-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-UNSAFE-MATH-NO-FAST-MATH %s +// CHECK-UNSAFE-MATH-NO-FAST-MATH: "-cc1" +// CHECK-UNSAFE-MATH-NO-FAST-MATH-NOT: "-menable-unsafe-fp-math" +// // Check that various umbrella flags also enable these frontend options. // RUN: %clang -### -ffast-math -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO-INFS %s @@ -63,12 +105,19 @@ // impact remains even if every optimization is disabled. // RUN: %clang -### -ffast-math -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-FAST-MATH %s +// RUN: %clang -### -fno-fast-math -ffast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FAST-MATH %s // RUN: %clang -### -ffast-math -fno-finite-math-only \ // RUN: -fno-unsafe-math-optimizations -fmath-errno -c %s 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-FAST-MATH %s // CHECK-FAST-MATH: "-cc1" // CHECK-FAST-MATH: "-ffast-math" // +// RUN: %clang -### -ffast-math -fno-fast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-FAST-MATH %s +// CHECK-NO-FAST-MATH: "-cc1" +// CHECK-NO-FAST-MATH-NOT: "-ffast-math" +// // Check various means of disabling these flags, including disabling them after // they've been enabled via an umbrella flag. // RUN: %clang -### -fno-honor-infinities -fhonor-infinities -c %s 2>&1 \ |