Index: cfe/trunk/docs/UsersManual.rst =================================================================== --- cfe/trunk/docs/UsersManual.rst +++ cfe/trunk/docs/UsersManual.rst @@ -1075,6 +1075,15 @@ ``Inf``, and * ``+0`` and ``-0`` are interchangeable. +.. option:: -fdenormal-fp-math=[values] + + Select which denormal numbers the code is permitted to require. + + Valid values are: ``ieee``, ``preserve-sign``, and ``positive-zero``, + which correspond to IEEE 754 denormal numbers, the sign of a + flushed-to-zero number is preserved in the sign of 0, denormals are + flushed to positive zero, respectively. + .. option:: -fwhole-program-vtables Enable whole-program vtable optimizations, such as single-implementation Index: cfe/trunk/include/clang/Driver/Options.td =================================================================== --- cfe/trunk/include/clang/Driver/Options.td +++ cfe/trunk/include/clang/Driver/Options.td @@ -626,6 +626,7 @@ def : Flag<["-"], "fextended-identifiers">, Group; def : Flag<["-"], "fno-extended-identifiers">, Group, Flags<[Unsupported]>; def fhosted : Flag<["-"], "fhosted">, Group; +def fdenormal_fp_math_EQ : Joined<["-"], "fdenormal-fp-math=">, Group, Flags<[CC1Option]>; def ffast_math : Flag<["-"], "ffast-math">, Group, Flags<[CC1Option]>, HelpText<"Allow aggressive, lossy floating-point optimizations">; def fno_fast_math : Flag<["-"], "fno-fast-math">, Group; @@ -740,8 +741,8 @@ // This option was originally misspelt "infinites" [sic]. def : Flag<["-"], "fhonor-infinites">, Alias; def : Flag<["-"], "fno-honor-infinites">, Alias; -def ftrapping_math : Flag<["-"], "ftrapping-math">, Group; -def fno_trapping_math : Flag<["-"], "fno-trapping-math">, Group; +def ftrapping_math : Flag<["-"], "ftrapping-math">, Group, Flags<[CC1Option]>; +def fno_trapping_math : Flag<["-"], "fno-trapping-math">, Group, Flags<[CC1Option]>; def ffp_contract : Joined<["-"], "ffp-contract=">, Group, Flags<[CC1Option]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)" " | on (according to FP_CONTRACT pragma, default) | off (never fuse)">; Index: cfe/trunk/include/clang/Frontend/CodeGenOptions.h =================================================================== --- cfe/trunk/include/clang/Frontend/CodeGenOptions.h +++ cfe/trunk/include/clang/Frontend/CodeGenOptions.h @@ -121,6 +121,9 @@ /// The ABI to use for passing floating point arguments. std::string FloatABI; + /// The floating-point denormal mode to use. + std::string FPDenormalMode; + /// The float precision limit to use, if non-empty. std::string LimitFloatPrecision; Index: cfe/trunk/include/clang/Frontend/CodeGenOptions.def =================================================================== --- cfe/trunk/include/clang/Frontend/CodeGenOptions.def +++ cfe/trunk/include/clang/Frontend/CodeGenOptions.def @@ -107,6 +107,7 @@ CODEGENOPT(NoInfsFPMath , 1, 0) ///< Assume FP arguments, results not +-Inf. CODEGENOPT(NoSignedZeros , 1, 0) ///< Allow ignoring the signedness of FP zero CODEGENOPT(ReciprocalMath , 1, 0) ///< Allow FP divisions to be reassociated. +CODEGENOPT(NoTrappingMath , 1, 0) ///< Set when -fno-trapping-math is enabled. CODEGENOPT(NoInline , 1, 0) ///< Set when -fno-inline is enabled. ///< Disables use of the inline keyword. CODEGENOPT(NoNaNsFPMath , 1, 0) ///< Assume FP arguments, results not NaN. Index: cfe/trunk/lib/CodeGen/CGCall.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGCall.cpp +++ cfe/trunk/lib/CodeGen/CGCall.cpp @@ -1722,6 +1722,13 @@ FuncAttrs.addAttribute("less-precise-fpmad", llvm::toStringRef(CodeGenOpts.LessPreciseFPMAD)); + + if (!CodeGenOpts.FPDenormalMode.empty()) + FuncAttrs.addAttribute("denormal-fp-math", + CodeGenOpts.FPDenormalMode); + + FuncAttrs.addAttribute("no-trapping-math", + llvm::toStringRef(CodeGenOpts.NoTrappingMath)); FuncAttrs.addAttribute("no-infs-fp-math", llvm::toStringRef(CodeGenOpts.NoInfsFPMath)); FuncAttrs.addAttribute("no-nans-fp-math", Index: cfe/trunk/lib/Driver/Tools.cpp =================================================================== --- cfe/trunk/lib/Driver/Tools.cpp +++ cfe/trunk/lib/Driver/Tools.cpp @@ -4369,6 +4369,12 @@ if (ReciprocalMath) CmdArgs.push_back("-freciprocal-math"); + if (!TrappingMath) + CmdArgs.push_back("-fno-trapping-math"); + + if (Args.hasArg(options::OPT_fdenormal_fp_math_EQ)) + Args.AddLastArg(CmdArgs, options::OPT_fdenormal_fp_math_EQ); + // Validate and pass through -fp-contract option. if (Arg *A = Args.getLastArg(options::OPT_ffast_math, FastMathAliasOption, options::OPT_fno_fast_math, Index: cfe/trunk/lib/Frontend/CompilerInvocation.cpp =================================================================== --- cfe/trunk/lib/Frontend/CompilerInvocation.cpp +++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp @@ -576,6 +576,7 @@ Opts.CorrectlyRoundedDivSqrt = Args.hasArg(OPT_cl_fp32_correctly_rounded_divide_sqrt); Opts.ReciprocalMath = Args.hasArg(OPT_freciprocal_math); + Opts.NoTrappingMath = Args.hasArg(OPT_fno_trapping_math); Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss); Opts.BackendOptions = Args.getAllArgValues(OPT_backend_option); Opts.NumRegisterParameters = getLastArgIntValue(Args, OPT_mregparm, 0, Diags); @@ -794,6 +795,18 @@ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val; } + if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) { + StringRef Val = A->getValue(); + if (Val == "ieee") + Opts.FPDenormalMode = "ieee"; + else if (Val == "preserve-sign") + Opts.FPDenormalMode = "preserve-sign"; + else if (Val == "positive-zero") + Opts.FPDenormalMode = "positive-zero"; + else + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val; + } + if (Arg *A = Args.getLastArg(OPT_fpcc_struct_return, OPT_freg_struct_return)) { if (A->getOption().matches(OPT_fpcc_struct_return)) { Opts.setStructReturnConvention(CodeGenOptions::SRCK_OnStack); Index: cfe/trunk/test/CodeGen/denormalfpmode.c =================================================================== --- cfe/trunk/test/CodeGen/denormalfpmode.c +++ cfe/trunk/test/CodeGen/denormalfpmode.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -S -fdenormal-fp-math=ieee %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-IEEE +// RUN: %clang_cc1 -S -fdenormal-fp-math=preserve-sign %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-PS +// RUN: %clang_cc1 -S -fdenormal-fp-math=positive-zero %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-PZ + +// CHECK-LABEL: main +// CHECK-IEEE: attributes #0 = {{.*}}"denormal-fp-math"="ieee"{{.*}} +// CHECK-PS: attributes #0 = {{.*}}"denormal-fp-math"="preserve-sign"{{.*}} +// CHECK-PZ: attributes #0 = {{.*}}"denormal-fp-math"="positive-zero"{{.*}} + +int main() { + return 0; +} Index: cfe/trunk/test/CodeGen/noexceptionsfpmath.c =================================================================== --- cfe/trunk/test/CodeGen/noexceptionsfpmath.c +++ cfe/trunk/test/CodeGen/noexceptionsfpmath.c @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -S -fno-trapping-math %s -emit-llvm -o - | FileCheck %s + +// CHECK-LABEL: main +// CHECK: attributes #0 = {{.*}}"no-trapping-math"="true"{{.*}} + +int main() { + return 0; +} Index: cfe/trunk/test/Driver/fast-math.c =================================================================== --- cfe/trunk/test/Driver/fast-math.c +++ cfe/trunk/test/Driver/fast-math.c @@ -231,3 +231,20 @@ // CHECK-NO-UNSAFE-MATH: "-cc1" // CHECK-NO-UNSAFE-MATH-NOT: "-menable-unsafe-fp-math" // CHECK-NO-UNSAFE-MATH: "-o" +// +// RUN: %clang -### -fexceptions-fp-math -fno-exceptions-fp-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-FP-EXCEPTIONS %s +// RUN: %clang -### -fno-exceptions-fp-math -fexceptions-fp-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FP-EXCEPTIONS %s +// CHECK-NO-FP-EXCEPTIONS: "-fno-exceptions-fp-math" +// CHECK-FP-EXCEPTIONS-NOT: "-fno-exceptions-fp-math" +// +// RUN: %clang -### -fdenormal-fp-math=ieee -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FP-DENORMAL-IEEE %s +// RUN: %clang -### -fdenormal-fp-math=preserve-sign -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FP-DENORMAL-PS %s +// RUN: %clang -### -fdenormal-fp-math=positive-zero -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FP-DENORMAL-PZ %s +// CHECK-FP-DENORMAL-IEEE: "-fdenormal-fp-math=ieee" +// CHECK-FP-DENORMAL-PS: "-fdenormal-fp-math=preserve-sign" +// CHECK-FP-DENORMAL-PZ: "-fdenormal-fp-math=positive-zero"