[clang] [flang] [Flang][Driver] Override -ffast-math floating point contraction with -ffp-contract= (PR #213574)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Aug 2 18:18:46 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-driver
Author: Shunsuke Watanabe (s-watanabe314)
<details>
<summary>Changes</summary>
This patch allows overriding the floating point contract settings implied by -ffast-math by explicitly specifying -ffp-contract=. The final floating point contract mode follows the usual last-flag-wins behavior. In addition, -fno-fast-math only cancels the effects of -ffast-math and preserves any explicitly specified -ffp-contract= setting.
A warning is emitted when an explicit -ffp-contract= option overrides the floating point contract mode implied by -ffast-math.
This behavior is consistent with Clang.
---
Full diff: https://github.com/llvm/llvm-project/pull/213574.diff
2 Files Affected:
- (modified) clang/lib/Driver/ToolChains/Flang.cpp (+35-20)
- (modified) flang/test/Driver/fast-math.f90 (+27)
``````````diff
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 650148de1374a..5ad2b5540aa42 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -797,6 +797,8 @@ void Flang::addOffloadOptions(Compilation &C, const InputInfoList &Inputs,
static void addFloatingPointOptions(const Driver &D, const ArgList &Args,
ArgStringList &CmdArgs) {
StringRef FPContract;
+ StringRef LastSeenFfpContractOption;
+ StringRef LastFpContractOverrideOption;
bool HonorINFs = true;
bool HonorNaNs = true;
bool ApproxFunc = false;
@@ -807,23 +809,6 @@ static void addFloatingPointOptions(const Driver &D, const ArgList &Args,
StringRef LastComplexRangeOption;
LangOptions::ComplexRangeKind Range = LangOptions::ComplexRangeKind::CX_None;
- if (const Arg *A = Args.getLastArg(options::OPT_ffp_contract)) {
- const StringRef Val = A->getValue();
- if (Val == "fast" || Val == "off") {
- FPContract = Val;
- } else if (Val == "on") {
- // Warn instead of error because users might have makefiles written for
- // gfortran (which accepts -ffp-contract=on)
- D.Diag(diag::warn_drv_unsupported_option_for_flang)
- << Val << A->getOption().getName() << "off";
- FPContract = "off";
- } else
- // Clang's "fast-honor-pragmas" option is not supported because it is
- // non-standard
- D.Diag(diag::err_drv_unsupported_option_argument)
- << A->getSpelling() << Val;
- }
-
for (const Arg *A : Args) {
auto optId = A->getOption().getID();
switch (optId) {
@@ -886,6 +871,32 @@ static void addFloatingPointOptions(const Driver &D, const ArgList &Args,
case options::OPT_fno_reciprocal_math:
ReciprocalMath = false;
break;
+ case options::OPT_ffp_contract: {
+ StringRef Val = A->getValue();
+ if (Val == "fast" || Val == "off") {
+ if (Val != FPContract && LastFpContractOverrideOption != "") {
+ D.Diag(clang::diag::warn_drv_overriding_option)
+ << LastFpContractOverrideOption
+ << Args.MakeArgString("-ffp-contract=" + Val);
+ }
+ FPContract = Val;
+ LastSeenFfpContractOption = Val;
+ } else if (Val == "on") {
+ // Warn instead of error because users might have makefiles written for
+ // gfortran (which accepts -ffp-contract=on)
+ D.Diag(diag::warn_drv_unsupported_option_for_flang)
+ << Val << A->getOption().getName() << "off";
+ FPContract = "off";
+ LastSeenFfpContractOption = "off";
+ } else {
+ // Clang's "fast-honor-pragmas" option is not supported because it is
+ // non-standard
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getSpelling() << Val;
+ }
+ LastFpContractOverrideOption = "";
+ break;
+ }
case options::OPT_Ofast:
[[fallthrough]];
case options::OPT_ffast_math:
@@ -896,6 +907,7 @@ static void addFloatingPointOptions(const Driver &D, const ArgList &Args,
ApproxFunc = true;
SignedZeros = false;
FPContract = "fast";
+ LastFpContractOverrideOption = "-ffast-math";
setComplexRange(D, A->getSpelling(),
LangOptions::ComplexRangeKind::CX_Basic,
LastComplexRangeOption, Range);
@@ -908,9 +920,12 @@ static void addFloatingPointOptions(const Driver &D, const ArgList &Args,
ApproxFunc = false;
SignedZeros = true;
// -fno-fast-math should undo -ffast-math so I return FPContract to the
- // default. It is important to check it is "fast" (the default) so that
- // --ffp-contract=off -fno-fast-math --> -ffp-contract=off
- if (FPContract == "fast")
+ // default. If -ffp-contract= was explicitly specified, restore the
+ // user-requested value from LastSeenFfpContractOption so that
+ // -ffp-contract=off -fno-fast-math --> -ffp-contract=off
+ if (LastSeenFfpContractOption != "")
+ FPContract = LastSeenFfpContractOption;
+ else
FPContract = "";
setComplexRange(D, A->getSpelling(),
LangOptions::ComplexRangeKind::CX_None,
diff --git a/flang/test/Driver/fast-math.f90 b/flang/test/Driver/fast-math.f90
index 22e339dc8ace9..3a6a48c98ab0c 100644
--- a/flang/test/Driver/fast-math.f90
+++ b/flang/test/Driver/fast-math.f90
@@ -64,12 +64,39 @@
! CHECK-TO-COMPS-SAME: -mreassociate
! CHECK-TO-COMPS-SAME: -freciprocal-math
+! Check if -ffast-math component flags can be disabled
+! RUN: %flang -ffast-math \
+! RUN: -ffp-contract=off \
+! RUN: -fhonor-infinities \
+! RUN: -fhonor-nans \
+! RUN: -fno-approx-func \
+! RUN: -fsigned-zeros \
+! RUN: -fno-associative-math \
+! RUN: -fno-reciprocal-math \
+! RUN: -fsyntax-only -### %s -o %t 2>&1 \
+! RUN: | FileCheck --check-prefix=CHECK-TO-COMPS-DIS %s
+! CHECK-TO-COMPS-DIS: warning: overriding '-ffast-math' option with '-ffp-contract=off' [-Woverriding-option]
+! CHECK-TO-COMPS-DIS: -fc1
+! CHECK-TO-COMPS-DIS-SAME: -ffp-contract=off
+! CHECK-TO-COMPS-DIS-NOT: -menable-no-infs
+! CHECK-TO-COMPS-DIS-NOT: -menable-no-nans
+! CHECK-TO-COMPS-DIS-NOT: -fapprox-func
+! CHECK-TO-COMPS-DIS-NOT: -fno-signed-zeros
+! CHECK-TO-COMPS-DIS-NOT: -mreassociate
+! CHECK-TO-COMPS-DIS-NOT: -freciprocal-math
+
! Check that -fno-fast-math doesn't clobber -ffp-contract
! RUN: %flang -ffp-contract=off -fno-fast-math -fsyntax-only -### %s -o %t 2>&1 \
! RUN: | FileCheck --check-prefix=CHECK-CONTRACT %s
! CHECK-CONTRACT: -fc1
! CHECK-CONTRACT-SAME: -ffp-contract=off
+! Check that -fno-fast-math only disables -ffast-math.
+! RUN: %flang -ffp-contract=off -ffast-math -fno-fast-math -fsyntax-only -### %s -o %t 2>&1 \
+! RUN: | FileCheck --check-prefix=CHECK-CONTRACT-NOFAST %s
+! CHECK-CONTRACT-NOFAST: -fc1
+! CHECK-CONTRACT-NOFAST-SAME: -ffp-contract=off
+
! Check that -ffast-math causes us to link to crtfastmath.o
! UNSUPPORTED: system-windows
! UNSUPPORTED: target=powerpc{{.*}}
``````````
</details>
https://github.com/llvm/llvm-project/pull/213574
More information about the cfe-commits
mailing list