diff options
-rw-r--r-- | include/clang/Basic/LangOptions.def | 1 | ||||
-rw-r--r-- | include/clang/Driver/ArgList.h | 2 | ||||
-rw-r--r-- | include/clang/Driver/CC1Options.td | 7 | ||||
-rw-r--r-- | include/clang/Driver/Options.td | 22 | ||||
-rw-r--r-- | lib/Driver/ArgList.cpp | 18 | ||||
-rw-r--r-- | lib/Driver/Tools.cpp | 102 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 7 | ||||
-rw-r--r-- | test/Driver/fast-math.c | 119 |
8 files changed, 255 insertions, 23 deletions
diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index 1f7bcd6f94..6c1038ee1d 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -100,6 +100,7 @@ VALUE_LANGOPT(PICLevel , 2, 0, "__PIC__ level") LANGOPT(GNUInline , 1, 0, "GNU inline semantics") LANGOPT(NoInline , 1, 0, "__NO_INLINE__ predefined macro") LANGOPT(Deprecated , 1, 0, "__DEPRECATED predefined macro") +LANGOPT(FastMath , 1, 0, "__FAST_MATH__ predefined macro") BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __weak/__strong ivars") diff --git a/include/clang/Driver/ArgList.h b/include/clang/Driver/ArgList.h index 04faf64dc5..f9698048b2 100644 --- a/include/clang/Driver/ArgList.h +++ b/include/clang/Driver/ArgList.h @@ -185,6 +185,8 @@ namespace driver { Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const; Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2, OptSpecifier Id3) const; + Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2, + OptSpecifier Id3, OptSpecifier Id4) const; /// getArgString - Return the input argument string at \arg Index. virtual const char *getArgString(unsigned Index) const = 0; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index d275af24f2..ec6e03bf76 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -170,6 +170,9 @@ def menable_no_infinities : Flag<"-menable-no-infs">, HelpText<"Allow optimization to assume there are no infinities.">; def menable_no_nans : Flag<"-menable-no-nans">, HelpText<"Allow optimization to assume there are no NaNs.">; +def menable_unsafe_fp_math : Flag<"-menable-unsafe-fp-math">, + HelpText<"Allow unsafe floating-point math optimizations which may decrease " + "precision">; def mfloat_abi : Separate<"-mfloat-abi">, HelpText<"The float ABI to use">; def mno_global_merge : Flag<"-mno-global-merge">, @@ -482,6 +485,10 @@ def fcxx_exceptions : Flag<"-fcxx-exceptions">, HelpText<"Enable C++ exceptions">; def fsjlj_exceptions : Flag<"-fsjlj-exceptions">, HelpText<"Use SjLj style exceptions">; +def ffast_math : Flag<"-ffast-math">, + 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 ffreestanding : Flag<"-ffreestanding">, HelpText<"Assert that the compilation takes place in a freestanding environment">; def fgnu_runtime : Flag<"-fgnu-runtime">, diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 892a972a62..08b3f03eae 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -319,8 +319,23 @@ def ferror_limit_EQ : Joined<"-ferror-limit=">, Group<f_Group>; def fexceptions : Flag<"-fexceptions">, Group<f_Group>; def fextdirs_EQ : Joined<"-fextdirs=">, Group<f_Group>; def fhosted : Flag<"-fhosted">, Group<f_Group>; -def ffast_math : Flag<"-ffast-math">, Group<clang_ignored_f_Group>; +def ffast_math : Flag<"-ffast-math">, Group<f_Group>; +def fmath_errno : Flag<"-fmath-errno">, Group<f_Group>; +def fno_math_errno : Flag<"-fno-math-errno">, Group<f_Group>; +def fsignaling_math : Flag<"-fsignaling-math">, Group<f_Group>; +def fno_signaling_math : Flag<"-fno-signaling-math">, Group<f_Group>; +def funsafe_math_optimizations : Flag<"-funsafe-math-optimizations">, + Group<f_Group>; +def fno_unsafe_math_optimizations : Flag<"-fno-unsafe-math-optimizations">, + Group<f_Group>; +def fassociative_math : Flag<"-fassociative-math">, Group<f_Group>; +def fno_associative_math : Flag<"-fno-associative-math">, Group<f_Group>; +def freciprocal_math : Flag<"-freciprocal-math">, Group<f_Group>; +def fno_reciprocal_math : Flag<"-fno-reciprocal-math">, Group<f_Group>; def ffinite_math_only : Flag<"-ffinite-math-only">, Group<f_Group>; +def fno_finite_math_only : Flag<"-fno-finite-math-only">, Group<f_Group>; +def fsigned_zeros : Flag<"-fsigned-zeros">, Group<f_Group>; +def fno_signed_zeros : Flag<"-fno-signed-zeros">, Group<f_Group>; def fhonor_nans : Flag<"-fhonor-nans">, Group<f_Group>; def fno_honor_nans : Flag<"-fno-honor-nans">, Group<f_Group>; def fhonor_infinities : Flag<"-fhonor-infinities">, Group<f_Group>; @@ -330,6 +345,8 @@ def fhonor_infinites : Flag<"-fhonor-infinites">, Group<f_Group>, Alias<fhonor_infinities>; def fno_honor_infinites : Flag<"-fno-honor-infinites">, Group<f_Group>, Alias<fno_honor_infinities>; +def ftrapping_math : Flag<"-ftrapping-math">, Group<f_Group>; +def fno_trapping_math : Flag<"-fno-trapping-math">, Group<f_Group>; def ffor_scope : Flag<"-ffor-scope">, Group<f_Group>; def fno_for_scope : Flag<"-fno-for-scope">, Group<f_Group>; @@ -355,7 +372,6 @@ def flto : Flag<"-flto">, Group<f_Group>; def fno_lto : Flag<"-fno-lto">, Group<f_Group>; def fmacro_backtrace_limit_EQ : Joined<"-fmacro-backtrace-limit=">, Group<f_Group>; -def fmath_errno : Flag<"-fmath-errno">, Group<f_Group>; def fmerge_all_constants : Flag<"-fmerge-all-constants">, Group<f_Group>; def fmessage_length_EQ : Joined<"-fmessage-length=">, Group<f_Group>; def fms_extensions : Flag<"-fms-extensions">, Group<f_Group>; @@ -394,7 +410,6 @@ def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, Group<f_Gr def fno_elide_constructors : Flag<"-fno-elide-constructors">, Group<f_Group>; def fno_eliminate_unused_debug_symbols : Flag<"-fno-eliminate-unused-debug-symbols">, Group<f_Group>; def fno_exceptions : Flag<"-fno-exceptions">, Group<f_Group>; -def fno_finite_math_only : Flag<"-fno-finite-math-only">, Group<clang_ignored_f_Group>; def fno_gnu_keywords : Flag<"-fno-gnu-keywords">, Group<f_Group>; def fno_inline_functions : Flag<"-fno-inline-functions">, Group<clang_ignored_f_Group>; def fno_inline : Flag<"-fno-inline">, Group<clang_ignored_f_Group>; @@ -402,7 +417,6 @@ def fno_keep_inline_functions : Flag<"-fno-keep-inline-functions">, Group<clang_ def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">, Group<f_Group>; def fno_limit_debug_info : Flag<"-fno-limit-debug-info">, Group<f_Group>, HelpText<"Do not limit debug information produced to reduce size of debug binary">; -def fno_math_errno : Flag<"-fno-math-errno">, Group<f_Group>; def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, Group<f_Group>; def fno_ms_extensions : Flag<"-fno-ms-extensions">, Group<f_Group>; def fno_ms_compatibility : Flag<"-fno-ms-compatibility">, Group<f_Group>; diff --git a/lib/Driver/ArgList.cpp b/lib/Driver/ArgList.cpp index ca9b944950..3c9e71d6f8 100644 --- a/lib/Driver/ArgList.cpp +++ b/lib/Driver/ArgList.cpp @@ -122,6 +122,24 @@ Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, return Res; } +Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, + OptSpecifier Id2, OptSpecifier Id3, + OptSpecifier Id4) const { + Arg *Res = 0; + for (const_iterator it = begin(), ie = end(); it != ie; ++it) { + if ((*it)->getOption().matches(Id0) || + (*it)->getOption().matches(Id1) || + (*it)->getOption().matches(Id2) || + (*it)->getOption().matches(Id3) || + (*it)->getOption().matches(Id4)) { + Res = *it; + Res->claim(); + } + } + + return Res; +} + bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const { if (Arg *A = getLastArg(Pos, Neg)) return A->getOption().matches(Pos); 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(); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index caeb416a59..0137774cf1 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -735,6 +735,8 @@ static void LangOptsToArgs(const LangOptions &Opts, Res.push_back("-fheinous-gnu-extensions"); // Optimize is implicit. // OptimizeSize is implicit. + if (Opts.FastMath) + Res.push_back("-ffast-math"); if (Opts.Static) Res.push_back("-static-define"); if (Opts.DumpRecordLayouts) @@ -1117,7 +1119,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.NoDwarf2CFIAsm = Args.hasArg(OPT_fno_dwarf2_cfi_asm); Opts.NoDwarfDirectoryAsm = Args.hasArg(OPT_fno_dwarf_directory_asm); Opts.SoftFloat = Args.hasArg(OPT_msoft_float); - Opts.UnsafeFPMath = Args.hasArg(OPT_cl_unsafe_math_optimizations) || + Opts.UnsafeFPMath = Args.hasArg(OPT_menable_unsafe_fp_math) || + Args.hasArg(OPT_cl_unsafe_math_optimizations) || Args.hasArg(OPT_cl_fast_relaxed_math); Opts.UnwindTables = Args.hasArg(OPT_munwind_tables); Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic"); @@ -1874,6 +1877,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, // FIXME: This is affected by other options (-fno-inline). Opts.NoInline = !Opt; + Opts.FastMath = Args.hasArg(OPT_ffast_math); + unsigned SSP = Args.getLastArgIntValue(OPT_stack_protector, 0, Diags); switch (SSP) { default: diff --git a/test/Driver/fast-math.c b/test/Driver/fast-math.c new file mode 100644 index 0000000000..aef7cc3624 --- /dev/null +++ b/test/Driver/fast-math.c @@ -0,0 +1,119 @@ +// Test that the GCC fast-math floating point flags get lowered to the correct +// permutation of Clang frontend flags. This is non-trivial for a few reasons. +// First, the GCC flags have many different and surprising effects. Second, +// LLVM only supports three switches which is more coarse grained than GCC's +// support. +// +// RUN: %clang -### -fno-honor-infinities -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-INFS %s +// CHECK-NO-INFS: "-cc1" +// CHECK-NO-INFS: "-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 -### -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 -### -fassociative-math -freciprocal-math -fno-signed-zeros \ +// RUN: -fno-trapping-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-UNSAFE-MATH %s +// CHECK-UNSAFE-MATH: "-cc1" +// CHECK-UNSAFE-MATH: "-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 +// RUN: %clang -### -ffast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-NANS %s +// RUN: %clang -### -ffast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-UNSAFE-MATH %s +// RUN: %clang -### -ffinite-math-only -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-INFS %s +// RUN: %clang -### -ffinite-math-only -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-NANS %s +// RUN: %clang -### -funsafe-math-optimizations -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-UNSAFE-MATH %s +// +// One umbrella flag is *really* weird and also changes the semantics of the +// program by adding a special preprocessor macro. Check that the frontend flag +// modeling this semantic change is provided. Also check that the semantic +// 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 -### -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" +// +// 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 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-NO-INFS %s +// RUN: %clang -### -ffinite-math-only -fhonor-infinities -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-NO-INFS %s +// RUN: %clang -### -ffinite-math-only -fno-finite-math-only -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-NO-INFS %s +// RUN: %clang -### -ffast-math -fhonor-infinities -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-NO-INFS %s +// RUN: %clang -### -ffast-math -fno-finite-math-only -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-NO-INFS %s +// CHECK-NO-NO-INFS: "-cc1" +// CHECK-NO-NO-INFS-NOT: "-menable-no-infs" +// CHECK-NO-NO-INFS: "-o" +// +// RUN: %clang -### -fno-honor-nans -fhonor-nans -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-NO-NANS %s +// RUN: %clang -### -ffinite-math-only -fhonor-nans -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-NO-NANS %s +// RUN: %clang -### -ffinite-math-only -fno-finite-math-only -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-NO-NANS %s +// RUN: %clang -### -ffast-math -fhonor-nans -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-NO-NANS %s +// RUN: %clang -### -ffast-math -fno-finite-math-only -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-NO-NANS %s +// CHECK-NO-NO-NANS: "-cc1" +// CHECK-NO-NO-NANS-NOT: "-menable-no-nans" +// CHECK-NO-NO-NANS: "-o" +// +// RUN: %clang -### -fassociative-math -freciprocal-math -fno-signed-zeros \ +// RUN: -fno-trapping-math -fno-associative-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s +// RUN: %clang -### -fassociative-math -freciprocal-math -fno-signed-zeros \ +// RUN: -fno-trapping-math -fno-reciprocal-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s +// RUN: %clang -### -fassociative-math -freciprocal-math -fno-signed-zeros \ +// RUN: -fno-trapping-math -fsigned-zeros -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s +// RUN: %clang -### -fassociative-math -freciprocal-math -fno-signed-zeros \ +// RUN: -fno-trapping-math -ftrapping-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s +// RUN: %clang -### -funsafe-math-optimizations -fno-associative-math -c %s \ +// RUN: 2>&1 | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s +// RUN: %clang -### -funsafe-math-optimizations -fno-reciprocal-math -c %s \ +// RUN: 2>&1 | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s +// RUN: %clang -### -funsafe-math-optimizations -fsigned-zeros -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s +// RUN: %clang -### -funsafe-math-optimizations -ftrapping-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s +// RUN: %clang -### -funsafe-math-optimizations -fno-unsafe-math-optimizations \ +// RUN: -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s +// RUN: %clang -### -ffast-math -fno-associative-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s +// RUN: %clang -### -ffast-math -fno-reciprocal-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s +// RUN: %clang -### -ffast-math -fsigned-zeros -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s +// RUN: %clang -### -ffast-math -ftrapping-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s +// RUN: %clang -### -ffast-math -fno-unsafe-math-optimizations -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-UNSAFE-MATH %s +// CHECK-NO-UNSAFE-MATH: "-cc1" +// CHECK-NO-UNSAFE-MATH-NOT: "-menable-unsafe-fp-math" +// CHECK-NO-UNSAFE-MATH: "-o" |