[flang-commits] [flang] 5d27e3a - [Flang][Driver] Override -ffast-math floating point contraction with -ffp-contract= (#213574)

via flang-commits flang-commits at lists.llvm.org
Tue Aug 11 17:00:04 PDT 2026


Author: Shunsuke Watanabe
Date: 2026-08-12T08:59:55+09:00
New Revision: 5d27e3a28f23ed73507d681b5f0cb96ab5f5d3f3

URL: https://github.com/llvm/llvm-project/commit/5d27e3a28f23ed73507d681b5f0cb96ab5f5d3f3
DIFF: https://github.com/llvm/llvm-project/commit/5d27e3a28f23ed73507d681b5f0cb96ab5f5d3f3.diff

LOG: [Flang][Driver] Override -ffast-math floating point contraction with -ffp-contract= (#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.

Added: 
    

Modified: 
    clang/lib/Driver/ToolChains/Flang.cpp
    flang/test/Driver/fast-math.f90

Removed: 
    


################################################################################
diff  --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index b2d709afcb4e2..a48e41159f367 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -894,6 +894,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;
@@ -904,23 +906,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) {
@@ -983,6 +968,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:
@@ -993,6 +1004,10 @@ static void addFloatingPointOptions(const Driver &D, const ArgList &Args,
       ApproxFunc = true;
       SignedZeros = false;
       FPContract = "fast";
+      if (A->getOption().getID() == options::OPT_Ofast)
+        LastFpContractOverrideOption = "-Ofast";
+      else
+        LastFpContractOverrideOption = "-ffast-math";
       setComplexRange(D, A->getSpelling(),
                       LangOptions::ComplexRangeKind::CX_Basic,
                       LastComplexRangeOption, Range);
@@ -1005,13 +1020,17 @@ 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,
                       LastComplexRangeOption, Range);
+      LastFpContractOverrideOption = "";
       break;
     }
 

diff  --git a/flang/test/Driver/fast-math.f90 b/flang/test/Driver/fast-math.f90
index 22e339dc8ace9..39c36863b9463 100644
--- a/flang/test/Driver/fast-math.f90
+++ b/flang/test/Driver/fast-math.f90
@@ -2,24 +2,24 @@
 ! frontend driver
 
 ! Check warning message for Ofast deprecation
-! RUN: %flang -Ofast -### %s -o %t 2>&1 | FileCheck %s
+! RUN: %flang -Ofast -### %s 2>&1 | FileCheck %s
 ! CHECK: warning: argument '-Ofast' is deprecated; use '-O3 -ffast-math -fstack-arrays -fno-protect-parens' for the same behavior, or '-O3 -fstack-arrays' to enable only conforming optimizations [-Wdeprecated-ofast]
 
 ! -Ofast => -ffast-math -O3 -fstack-arrays
-! RUN: %flang -Ofast -fsyntax-only -### %s -o %t 2>&1 \
+! RUN: %flang -Ofast -fsyntax-only -### %s 2>&1 \
 ! RUN:     | FileCheck --check-prefix=CHECK-OFAST %s
 ! CHECK-OFAST: -fc1
 ! CHECK-OFAST-SAME: -ffast-math
 ! CHECK-OFAST-SAME: -fstack-arrays
 ! CHECK-OFAST-SAME: -O3
 
-! RUN: %flang -fstack-arrays -fsyntax-only -### %s -o %t 2>&1 \
+! RUN: %flang -fstack-arrays -fsyntax-only -### %s 2>&1 \
 ! RUN:     | FileCheck --check-prefix=CHECK-STACK-ARRAYS %s
 ! CHECK-STACK-ARRAYS: -fc1
 ! CHECK-STACK-ARRAYS-SAME: -fstack-arrays
 
 ! -Ofast -fno-fast-math => -O3 -fstack-arrays
-! RUN: %flang -Ofast -fno-fast-math -fsyntax-only -### %s -o %t 2>&1 \
+! RUN: %flang -Ofast -fno-fast-math -fsyntax-only -### %s 2>&1 \
 ! RUN:     | FileCheck --check-prefix=CHECK-OFAST-NO-FAST %s
 ! CHECK-OFAST-NO-FAST: -fc1
 ! CHECK-OFAST-NO-FAST-NOT: -ffast-math
@@ -27,7 +27,7 @@
 ! CHECK-OFAST-NO-FAST-SAME: -O3
 
 ! -Ofast -fno-stack-arrays -> -O3 -ffast-math
-! RUN: %flang -Ofast -fno-stack-arrays -fsyntax-only -### %s -o %t 2>&1 \
+! RUN: %flang -Ofast -fno-stack-arrays -fsyntax-only -### %s 2>&1 \
 ! RUN:     | FileCheck --check-prefix=CHECK-OFAST-NO-SA %s
 ! CHECK-OFAST-NO-SA: -fc1
 ! CHECK-OFAST-NO-SA-SAME: -ffast-math
@@ -35,13 +35,13 @@
 ! CHECK-OFAST-NO-SA-SAME: -O3
 
 ! -ffast-math => -ffast-math
-! RUN: %flang -ffast-math -fsyntax-only -### %s -o %t 2>&1 \
+! RUN: %flang -ffast-math -fsyntax-only -### %s 2>&1 \
 ! RUN:     | FileCheck --check-prefix=CHECK-FFAST %s
 ! CHECK-FFAST: -fc1
 ! CHECK-FFAST-SAME: -ffast-math
 
 ! (component flags) => -ffast-math
-! RUN: %flang -fsyntax-only -### %s -o %t \
+! RUN: %flang -fsyntax-only -### %s \
 ! RUN:     -fno-honor-infinities \
 ! RUN:     -fno-honor-nans \
 ! RUN:     -fassociative-math \
@@ -54,7 +54,7 @@
 ! CHECK-FROM-COMPS-SAME: -ffast-math
 
 ! -ffast-math (followed by an alteration) => (component flags)
-! RUN: %flang -ffast-math -fhonor-infinities -fsyntax-only -### %s -o %t 2>&1 \
+! RUN: %flang -ffast-math -fhonor-infinities -fsyntax-only -### %s 2>&1 \
 ! RUN:     | FileCheck --check-prefix=CHECK-TO-COMPS %s
 ! CHECK-TO-COMPS: -fc1
 ! CHECK-TO-COMPS-SAME: -ffp-contract=fast
@@ -64,16 +64,57 @@
 ! 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 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: %flang -ffp-contract=off -fno-fast-math -fsyntax-only -### %s 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 2>&1 \
+! RUN:     | FileCheck --check-prefix=CHECK-CONTRACT-NOFAST %s
+! CHECK-CONTRACT-NOFAST: -fc1
+! CHECK-CONTRACT-NOFAST-SAME: -ffp-contract=off
+
+! Check that no warning is emitted after -fno-fast-math.
+! RUN: %flang -ffast-math -fno-fast-math -ffp-contract=off -fsyntax-only -### %s 2>&1 \
+! RUN:     | FileCheck --check-prefix=CHECK-NOFAST-CONTRACT %s
+! CHECK-NOFAST-CONTRACT-NOT: warning: overriding '-ffast-math' option with '-ffp-contract=off' [-Woverriding-option]
+! CHECK-NOFAST-CONTRACT: -fc1
+! CHECK-NOFAST-CONTRACT-SAME: -ffp-contract=off
+
+! Check that -Ofast is overridden.
+! RUN: %flang -Ofast -ffp-contract=off -fsyntax-only -### %s 2>&1 \
+! RUN:     | FileCheck --check-prefix=CHECK-OFAST-CONTRACT %s
+! CHECK-OFAST-CONTRACT: warning: overriding '-Ofast' option with '-ffp-contract=off' [-Woverriding-option]
+! CHECK-OFAST-CONTRACT: -fc1
+! CHECK-OFAST-CONTRACT-SAME: -ffp-contract=off
+
 ! Check that -ffast-math causes us to link to crtfastmath.o
 ! UNSUPPORTED: system-windows
 ! UNSUPPORTED: target=powerpc{{.*}}
-! RUN: %flang -ffast-math -### %s -o %t 2>&1 \
+! RUN: %flang -ffast-math -### %s 2>&1 \
 ! RUN:           --target=x86_64-unknown-linux -no-pie \
 ! RUN:           --sysroot=%S/../../../clang/test/Driver/Inputs/basic_linux_tree \
 ! RUN:     | FileCheck --check-prefix=CHECK-CRT %s


        


More information about the flang-commits mailing list