Index: clang/docs/UsersManual.rst =================================================================== --- clang/docs/UsersManual.rst +++ clang/docs/UsersManual.rst @@ -1403,6 +1403,54 @@ * ``-ffp-contract=fast`` +.. option:: -fno-fast-math + + Disable fast-math mode. This options disables unsafe floating-point + optimizations by preventing the compiler to make any tranformations that + could affect the results. + + This option implies: + + * ``-fhonor-infinities`` + + * ``-fhonor-nans`` + + * ``-fmath-errno`` + + * ``-fno-finite-math-only`` + + * ``-fno-associative-math`` + + * ``-fno-reciprocal-math`` + + * ``-fsigned-zeros`` + + * ``-fno-trapping-math`` + + * ``-ffp-contract=on`` + + There is ambiguity about what value should ``ffp-contract`` has, when + options ``-ffp-contract``, ``-ffast-math`` and ``-fno-fast-math`` are + combined. To keep the value of ``ffp-contract`` consistent, we define this + set of rules: + + * ``-ffast-math`` sets ``ffp-contract`` to ``fast``. + + * ``-fno-fast-math`` sets ``-ffp-contract`` to ``on`` (``fast`` for CUDA and HIP). + + * If ``-ffast-math`` and ``-ffp-contract`` are both seen, but + ``-fno-fast-math`` has not been seen after the last instance of + ``-ffast-math``, the ``ffp-contract`` will get the value of whichever option + was last seen. + + * If ``-fno-fast-math`` is seen and ``-ffp-contract`` has been seen at least + once, the ``ffp-contract`` will get the value of the last seen value of + ``-ffp-contract``. + + * If ``-fno-fast-math`` is seen and ``-ffp-contract`` has not been seen, the + ``ffp-contract`` setting is determined by the default value of + ``ffp-contract``. + .. option:: -fdenormal-fp-math= Select which denormal numbers the code is permitted to require. Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -2774,6 +2774,8 @@ // CUDA and HIP don't rely on the frontend to pass an ffp-contract option. // If one wasn't given by the user, don't pass it here. StringRef FPContract; + StringRef LastSeenFfpContractOption; + StringRef LastSeenFfastMathOption; if (!JA.isDeviceOffloading(Action::OFK_Cuda) && !JA.isOffloading(Action::OFK_HIP)) FPContract = "on"; @@ -2924,8 +2926,10 @@ // -ffp-model=precise sets PreciseFPModel to on and Val to // "precise". FPContract is set. ; - } else if (Val.equals("fast") || Val.equals("on") || Val.equals("off")) + } else if (Val.equals("fast") || Val.equals("on") || Val.equals("off")) { FPContract = Val; + LastSeenFfpContractOption = Val; + } else D.Diag(diag::err_drv_unsupported_option_argument) << A->getOption().getName() << Val; @@ -3019,6 +3023,7 @@ RoundingFPMath = false; // If fast-math is set then set the fp-contract mode to fast. FPContract = "fast"; + LastSeenFfastMathOption = "fast"; break; case options::OPT_fno_fast_math: HonorINFs = true; @@ -3035,13 +3040,12 @@ DenormalFPMath = DefaultDenormalFPMath; DenormalFP32Math = llvm::DenormalMode::getIEEE(); if (!JA.isDeviceOffloading(Action::OFK_Cuda) && - !JA.isOffloading(Action::OFK_HIP)) - if (FPContract == "fast") { + !JA.isOffloading(Action::OFK_HIP)) { + if (LastSeenFfpContractOption != "") { + FPContract = LastSeenFfpContractOption; + } else if (LastSeenFfastMathOption != "") FPContract = "on"; - D.Diag(clang::diag::warn_drv_overriding_flag_option) - << "-ffp-contract=fast" - << "-ffp-contract=on"; - } + } break; } if (StrictFPModel) { Index: clang/test/CodeGen/ffp-contract-option.c =================================================================== --- clang/test/CodeGen/ffp-contract-option.c +++ clang/test/CodeGen/ffp-contract-option.c @@ -35,7 +35,7 @@ // RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-FPC-ON // RUN: %clang -Xclang -no-opaque-pointers -S -emit-llvm -ffp-contract=fast -fno-fast-math \ -// RUN: %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-FPC-ON +// RUN: %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-CONTRACTFAST // RUN: %clang -Xclang -no-opaque-pointers -S -emit-llvm -ffp-contract=on -fno-fast-math \ // RUN: %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-FPC-ON Index: clang/test/Driver/fp-contract.c =================================================================== --- /dev/null +++ clang/test/Driver/fp-contract.c @@ -0,0 +1,114 @@ +// Test that -ffp-contract is set to the right value when combined with +// the options -ffast-math and -fno-fast-math. + +// RUN: %clang -### -ffast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s +// CHECK-FPC-FAST: "-ffp-contract=fast" + +// RUN: %clang -### -fno-fast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-ON %s + +// RUN: %clang -### -ffast-math -ffp-contract=on -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-ON %s +// CHECK-FPC-ON: "-ffp-contract=on" + +// RUN: %clang -### -ffast-math -ffp-contract=off -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-OFF %s +// CHECK-FPC-OFF: "-ffp-contract=off" + +// RUN: %clang -### -ffast-math -ffp-contract=fast -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s + +// RUN: %clang -### -ffp-contract=fast -ffast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s +// RUN: %clang -### -ffp-contract=on -ffast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s +// RUN: %clang -### -ffp-contract=off -ffast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s + +// RUN: %clang -### -ffp-contract=fast -fno-fast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s +// RUN: %clang -### -ffp-contract=on -fno-fast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-ON %s +// RUN: %clang -### -ffp-contract=off -fno-fast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-OFF %s + + +// RUN: %clang -### -ffast-math -ffp-contract=fast -ffp-contract=on -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-ON %s + +// RUN: %clang -### -ffast-math -ffp-contract=on -ffp-contract=off -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-OFF %s + +// RUN: %clang -### -ffast-math -ffp-contract=on -ffp-contract=fast -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s + +// RUN: %clang -### -ffast-math -ffp-contract=off -ffp-contract=on -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-ON %s + +// RUN: %clang -### -ffast-math -ffp-contract=off -ffp-contract=fast \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-FAST %s + +// RUN: %clang -### -ffast-math -ffp-contract=on -fno-fast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-ON %s + +// RUN: %clang -### -ffast-math -ffp-contract=off -fno-fast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-OFF %s + +// RUN: %clang -### -ffast-math -ffp-contract=fast -fno-fast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s + +// RUN: %clang -### -ffast-math -fno-fast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-ON %s + +// RUN: %clang -### -fno-fast-math -ffast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s + +// RUN: %clang -### -fno-fast-math -ffp-contract=on -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-ON %s + +// RUN: %clang -### -fno-fast-math -ffp-contract=off -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-OFF %s + +// RUN: %clang -### -fno-fast-math -ffp-contract=fast -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s + +// RUN: %clang -### -ffp-contract=fast -fno-fast-math -ffp-contract=on \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-ON %s + +// RUN: %clang -### -ffp-contract=fast -fno-fast-math -ffp-contract=off \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-OFF %s + +// RUN: %clang -### -ffp-contract=off -fno-fast-math -ffp-contract=fast \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-FAST %s + +// RUN: %clang -### -ffp-contract=off -fno-fast-math -ffp-contract=on \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-ON %s + +// RUN: %clang -### -ffp-contract=on -ffast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s + +// RUN: %clang -### -ffp-contract=off -ffast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s + +// RUN: %clang -### -ffp-contract=fast -ffast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s + +// RUN: %clang -### -ffp-contract=on -ffast-math -fno-fast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-ON %s + +// RUN: %clang -### -ffp-contract=off -ffast-math -fno-fast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-OFF %s + +// RUN: %clang -### -ffp-contract=fast -ffast-math -fno-fast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-FPC-FAST %s + +// RUN: %clang -### -fno-fast-math -ffast-math -ffp-contract=fast \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-FAST %s + +// RUN: %clang -### -fno-fast-math -ffast-math -ffp-contract=on \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-ON %s + +// RUN: %clang -### -fno-fast-math -ffast-math -ffp-contract=off \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=CHECK-FPC-OFF %s +