Floating Point Support in Clang
-------------------------------
+- The driver option ``-menable-unsafe-fp-math`` has been removed. To enable
+ unsafe floating-point optimizations use ``-funsafe-math-optimizations`` or
+ ``-ffast-math`` instead.
Internal API Changes
--------------------
PosFlag<SetTrue, [CC1Option], "Allow aggressive, lossy floating-point optimizations",
[cl_fast_relaxed_math.KeyPath]>,
NegFlag<SetFalse>>;
-def menable_unsafe_fp_math : Flag<["-"], "menable-unsafe-fp-math">, Flags<[CC1Option]>,
- HelpText<"Allow unsafe floating-point math optimizations which may decrease precision">,
- MarshallingInfoFlag<LangOpts<"UnsafeFPMath">>,
- ImpliedByAnyOf<[cl_unsafe_math_optimizations.KeyPath, ffast_math.KeyPath]>;
defm math_errno : BoolFOption<"math-errno",
LangOpts<"MathErrno">, DefaultFalse,
PosFlag<SetTrue, [CC1Option], "Require math functions to indicate errors by setting errno">,
} // end -f[no-]sanitize* flags
def funsafe_math_optimizations : Flag<["-"], "funsafe-math-optimizations">,
- Group<f_Group>;
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Allow unsafe floating-point math optimizations which may decrease precision">,
+ MarshallingInfoFlag<LangOpts<"UnsafeFPMath">>,
+ ImpliedByAnyOf<[cl_unsafe_math_optimizations.KeyPath, ffast_math.KeyPath]>;
def fno_unsafe_math_optimizations : Flag<["-"], "fno-unsafe-math-optimizations">,
Group<f_Group>;
def fassociative_math : Flag<["-"], "fassociative-math">, Group<f_Group>;
defm reciprocal_math : BoolFOption<"reciprocal-math",
LangOpts<"AllowRecip">, DefaultFalse,
PosFlag<SetTrue, [CC1Option], "Allow division operations to be reassociated",
- [menable_unsafe_fp_math.KeyPath]>,
+ [funsafe_math_optimizations.KeyPath]>,
NegFlag<SetFalse>>;
defm approx_func : BoolFOption<"approx-func", LangOpts<"ApproxFunc">, DefaultFalse,
PosFlag<SetTrue, [CC1Option], "Allow certain math function calls to be replaced "
"with an approximately equivalent calculation",
- [menable_unsafe_fp_math.KeyPath]>,
+ [funsafe_math_optimizations.KeyPath]>,
NegFlag<SetFalse>>;
defm finite_math_only : BoolFOption<"finite-math-only",
LangOpts<"FiniteMathOnly">, DefaultFalse,
defm signed_zeros : BoolFOption<"signed-zeros",
LangOpts<"NoSignedZero">, DefaultFalse,
NegFlag<SetTrue, [CC1Option], "Allow optimizations that ignore the sign of floating point zeros",
- [cl_no_signed_zeros.KeyPath, menable_unsafe_fp_math.KeyPath]>,
+ [cl_no_signed_zeros.KeyPath, funsafe_math_optimizations.KeyPath]>,
PosFlag<SetFalse>>;
def fhonor_nans : Flag<["-"], "fhonor-nans">, Group<f_Group>;
def fno_honor_nans : Flag<["-"], "fno-honor-nans">, Group<f_Group>;
MarshallingInfoFlag<LangOpts<"NoHonorNaNs">>, ImpliedByAnyOf<[ffinite_math_only.KeyPath]>;
def mreassociate : Flag<["-"], "mreassociate">,
HelpText<"Allow reassociation transformations for floating-point instructions">,
- MarshallingInfoFlag<LangOpts<"AllowFPReassoc">>, ImpliedByAnyOf<[menable_unsafe_fp_math.KeyPath]>;
+ MarshallingInfoFlag<LangOpts<"AllowFPReassoc">>, ImpliedByAnyOf<[funsafe_math_optimizations.KeyPath]>;
def mabi_EQ_ieeelongdouble : Flag<["-"], "mabi=ieeelongdouble">,
HelpText<"Use IEEE 754 quadruple-precision for long double">,
MarshallingInfoFlag<LangOpts<"PPCIEEELongDouble">>;
FuncAttrs.addAttribute("no-nans-fp-math", "true");
if (LangOpts.ApproxFunc)
FuncAttrs.addAttribute("approx-func-fp-math", "true");
- if (LangOpts.UnsafeFPMath)
+ if ((LangOpts.FastMath ||
+ !LangOpts.FastMath && LangOpts.AllowFPReassoc && LangOpts.AllowRecip &&
+ !LangOpts.FiniteMathOnly && LangOpts.NoSignedZero &&
+ LangOpts.ApproxFunc) &&
+ LangOpts.getDefaultFPContractMode() != LangOptions::FPModeKind::FPM_Off)
FuncAttrs.addAttribute("unsafe-fp-math", "true");
if (CodeGenOpts.SoftFloat)
FuncAttrs.addAttribute("use-soft-float", "true");
if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros &&
ApproxFunc && !TrappingMath)
- CmdArgs.push_back("-menable-unsafe-fp-math");
+ CmdArgs.push_back("-funsafe-math-optimizations");
if (!SignedZeros)
CmdArgs.push_back("-fno-signed-zeros");
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fno-signed-zeros -emit-llvm -o - %s | FileCheck -check-prefix CHECK-NO-SIGNED-ZEROS %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -mreassociate -emit-llvm -o - %s | FileCheck -check-prefix CHECK-REASSOC %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -freciprocal-math -emit-llvm -o - %s | FileCheck -check-prefix CHECK-RECIP %s
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -menable-unsafe-fp-math -emit-llvm -o - %s | FileCheck -check-prefix CHECK-UNSAFE %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -funsafe-math-optimizations -emit-llvm -o - %s | FileCheck -check-prefix CHECK-UNSAFE %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ffast-math -emit-llvm -o - %s | FileCheck -check-prefix CHECK-FAST %s
float fn(float);
--- /dev/null
+// RUN: %clang -c -ffast-math -emit-llvm -S -o - %s \
+// RUN: | FileCheck %s
+
+// RUN: %clang -c -funsafe-math-optimizations -emit-llvm -S -o - %s \
+// RUN: | FileCheck %s
+
+float foo(float a, float b) {
+ return a+b;
+}
+
+// CHECK: define{{.*}} float @foo(float noundef %a, float noundef %b) [[FAST_ATTRS:#[0-9]+]]
+// CHECK: attributes [[FAST_ATTRS]] = { {{.*}} "approx-func-fp-math"="true" {{.*}} "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" {{.*}} "unsafe-fp-math"="true"
// RUN: %clang_cc1 -Wno-implicit-function-declaration -fmath-errno -emit-llvm -o - %s -triple i386-unknown-unknown | FileCheck -check-prefix CHECK-YES %s
// RUN: %clang_cc1 -Wno-implicit-function-declaration -emit-llvm -o - %s -triple i386-unknown-unknown | FileCheck -check-prefix CHECK-NO %s
-// RUN: %clang_cc1 -Wno-implicit-function-declaration -menable-unsafe-fp-math -emit-llvm -o - %s -triple i386-unknown-unknown | FileCheck -check-prefix CHECK-FAST %s
+// RUN: %clang_cc1 -Wno-implicit-function-declaration -funsafe-math-optimizations -emit-llvm -o - %s -triple i386-unknown-unknown | FileCheck -check-prefix CHECK-FAST %s
// CHECK-YES-LABEL: define{{.*}} void @test_sqrt
// CHECK-NO-LABEL: define{{.*}} void @test_sqrt
// RUN: %clang_cc1 -x cuda %s -emit-llvm -mlink-builtin-bitcode %t.bc \
// RUN: -fdenormal-fp-math-f32=preserve-sign -o - \
-// RUN: -fcuda-is-device -menable-unsafe-fp-math -triple nvptx-unknown-unknown \
+// RUN: -fcuda-is-device -funsafe-math-optimizations -triple nvptx-unknown-unknown \
// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=FAST
// Wrap everything in extern "C" so we don't have to worry about name mangling
// EXTERNAL_I: "-isystem" "path"
// RUN: %clang_cl /fp:fast /fp:except -### -- %s 2>&1 | FileCheck -check-prefix=fpexcept %s
-// fpexcept-NOT: -menable-unsafe-fp-math
+// fpexcept-NOT: -funsafe-math-optimizations
// fpexcept: -ffp-exception-behavior=strict
// RUN: %clang_cl /fp:fast /fp:except /fp:except- -### -- %s 2>&1 | FileCheck -check-prefix=fpexcept_ %s
-// fpexcept_: -menable-unsafe-fp-math
+// fpexcept_: -funsafe-math-optimizations
// fpexcept_: -ffp-exception-behavior=ignore
// RUN: %clang_cl /fp:precise /fp:fast -### -- %s 2>&1 | FileCheck -check-prefix=fpfast %s
-// fpfast: -menable-unsafe-fp-math
+// fpfast: -funsafe-math-optimizations
// fpfast: -ffast-math
// RUN: %clang_cl /fp:fast /fp:precise -### -- %s 2>&1 | FileCheck -check-prefix=fpprecise %s
-// fpprecise-NOT: -menable-unsafe-fp-math
+// fpprecise-NOT: -funsafe-math-optimizations
// fpprecise-NOT: -ffast-math
// RUN: %clang_cl /fp:fast /fp:strict -### -- %s 2>&1 | FileCheck -check-prefix=fpstrict %s
-// fpstrict-NOT: -menable-unsafe-fp-math
+// fpstrict-NOT: -funsafe-math-optimizations
// fpstrict-NOT: -ffast-math
// fpstrict: -ffp-contract=off
// RUN: -fno-signed-zeros -fno-trapping-math -fapprox-func -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-UNSAFE-MATH %s
// CHECK-UNSAFE-MATH: "-cc1"
-// CHECK-UNSAFE-MATH: "-menable-unsafe-fp-math"
+// CHECK-UNSAFE-MATH: "-funsafe-math-optimizations"
// CHECK-UNSAFE-MATH: "-mreassociate"
//
// RUN: %clang -### -fno-fast-math -fno-math-errno -fassociative-math -freciprocal-math \
// RUN: -fno-signed-zeros -fno-trapping-math -fapprox-func -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"
+// CHECK-NO-FAST-MATH-UNSAFE-MATH: "-funsafe-math-optimizations"
// CHECK-NO-FAST-MATH-UNSAFE-MATH: "-mreassociate"
// The 2nd -fno-fast-math overrides -fassociative-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-UNSAFE-MATH-NO-FAST-MATH-NOT: "-funsafe-math-optimizations"
// CHECK-UNSAFE-MATH-NO-FAST-MATH-NOT: "-mreassociate"
//
// Check that various umbrella flags also enable these frontend options.
// 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-NOT: "-funsafe-math-optimizations"
// CHECK-NO_UNSAFE-MATH-NOT: "-mreassociate"
// CHECK-NO-UNSAFE-MATH: "-o"
// RUN: | FileCheck --check-prefix=CHECK-REASSOC-NO-UNSAFE-MATH %s
// CHECK-REASSOC-NO-UNSAFE-MATH: "-cc1"
-// CHECK-REASSOC-NO-UNSAFE-MATH-NOT: "-menable-unsafe-fp-math"
+// CHECK-REASSOC-NO_UNSAFE-MATH-NOT: "-funsafe-math-optimizations"
// CHECK-REASSOC-NO_UNSAFE-MATH: "-mreassociate"
-// CHECK-REASSOC-NO-UNSAFE-MATH-NOT: "-menable-unsafe-fp-math"
+// CHECK-REASSOC-NO-UNSAFE-MATH-NOT: "-funsafe-math-optimizations"
// CHECK-REASSOC-NO-UNSAFE-MATH: "-o"
// RUN: | FileCheck --check-prefix=CHECK-NO-REASSOC-NO-UNSAFE-MATH %s
// CHECK-NO-REASSOC-NO-UNSAFE-MATH: "-cc1"
-// CHECK-NO-REASSOC-NO-UNSAFE-MATH-NOT: "-menable-unsafe-fp-math"
+// CHECK-NO-REASSOC-NO_UNSAFE-MATH-NOT: "-funsafe-math-optimizations"
// CHECK-NO-REASSOC-NO_UNSAFE-MATH-NOT: "-mreassociate"
-// CHECK-NO-REASSOC-NO-UNSAFE-MATH-NOT: "-menable-unsafe-fp-math"
+// CHECK-NO-REASSOC-NO_UNSAFE-MATH-NOT: "-funsafe-math-optimizations"
// CHECK-NO-REASSOC-NO-UNSAFE-MATH: "-o"
// CHECK-FPM-FAST: "-cc1"
// CHECK-FPM-FAST: "-menable-no-infs"
// CHECK-FPM-FAST: "-menable-no-nans"
-// CHECK-FPM-FAST: "-menable-unsafe-fp-math"
+// CHECK-FPM-FAST: "-funsafe-math-optimizations"
// CHECK-FPM-FAST: "-fno-signed-zeros"
// CHECK-FPM-FAST: "-mreassociate"
// CHECK-FPM-FAST: "-freciprocal-math"
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fdenormal-fp-math=preserve-sign,preserve-sign -fsyntax-only %s -DDEFAULT -verify
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only %s -ffp-contract=fast -DPRECISE -verify
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only %s -ffp-contract=off -frounding-math -ffp-exception-behavior=strict -DSTRICT -verify
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -ffp-contract=fast -ffast-math -ffinite-math-only -fsyntax-only %s -DFAST -verify
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -menable-no-infs -menable-no-nans -funsafe-math-optimizations -fno-signed-zeros -mreassociate -freciprocal-math -ffp-contract=fast -ffast-math -ffinite-math-only -fsyntax-only %s -DFAST -verify
double a = 0.0;
double b = 1.0;
//
// * -cl-unsafe-math-optimizations
// * -cl-mad-enable
-// * -menable-unsafe-fp-math
+// * -funsafe-math-optimizations
// * -freciprocal-math
TEST_F(CommandLineTest, ImpliedBoolOptionsNoFlagPresent) {
ASSERT_THAT(GeneratedArgs,
Not(Contains(StrEq("-cl-unsafe-math-optimizations"))));
ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
- ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math"))));
+ ASSERT_THAT(GeneratedArgs,
+ Not(Contains(StrEq("-funsafe-math-optimizations"))));
ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
}
ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations")));
// Not generated - implied by the generated root flag.
ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
- ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math"))));
+ ASSERT_THAT(GeneratedArgs,
+ Not(Contains(StrEq("-funsafe-math-optimizations"))));
ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
}
TEST_F(CommandLineTest, ImpliedBoolOptionsAllFlagsPresent) {
const char *Args[] = {"-cl-unsafe-math-optimizations", "-cl-mad-enable",
- "-menable-unsafe-fp-math", "-freciprocal-math"};
+ "-funsafe-math-optimizations", "-freciprocal-math"};
ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
ASSERT_TRUE(Invocation.getLangOpts()->CLUnsafeMath);
ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations")));
// Not generated - implied by their generated parent.
ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
- ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math"))));
+ ASSERT_THAT(GeneratedArgs,
+ Not(Contains(StrEq("-funsafe-math-optimizations"))));
ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
}
TEST_F(CommandLineTest, ImpliedBoolOptionsImpliedFlagsPresent) {
- const char *Args[] = {"-cl-mad-enable", "-menable-unsafe-fp-math",
+ const char *Args[] = {"-cl-mad-enable", "-funsafe-math-optimizations",
"-freciprocal-math"};
ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
Not(Contains(StrEq("-cl-unsafe-math-optimizations"))));
// Generated - explicitly provided.
ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-mad-enable")));
- ASSERT_THAT(GeneratedArgs, Contains(StrEq("-menable-unsafe-fp-math")));
+ ASSERT_THAT(GeneratedArgs, Contains(StrEq("-funsafe-math-optimizations")));
// Not generated - implied by its generated parent.
ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
}
TEST_F(CommandLineTest, PresentAndNotImpliedGenerated) {
- const char *Args[] = {"-cl-mad-enable", "-menable-unsafe-fp-math"};
+ const char *Args[] = {"-cl-mad-enable", "-funsafe-math-optimizations"};
ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
// Present options that were not implied are generated.
ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-mad-enable")));
- ASSERT_THAT(GeneratedArgs, Contains(StrEq("-menable-unsafe-fp-math")));
+ ASSERT_THAT(GeneratedArgs, Contains(StrEq("-funsafe-math-optimizations")));
}
// Diagnostic option.