https://github.com/s-watanabe314 created https://github.com/llvm/llvm-project/pull/213574
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. >From 16e3989b586f7d351b3cf2a8b403f9fac49fc72c Mon Sep 17 00:00:00 2001 From: s-watanabe314 <[email protected]> Date: Tue, 16 Jun 2026 11:52:07 +0900 Subject: [PATCH] [Flang][Driver] Override -ffast-math floating point contraction with -ffp-contract= 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. --- clang/lib/Driver/ToolChains/Flang.cpp | 55 +++++++++++++++++---------- flang/test/Driver/fast-math.f90 | 27 +++++++++++++ 2 files changed, 62 insertions(+), 20 deletions(-) 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{{.*}} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
