[clang] [clang][Driver] Restore -cl-fast-relaxed-math fast-math cascade at cc1 level (PR #211768)
Wenju He via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 24 03:54:57 PDT 2026
https://github.com/wenju-he created https://github.com/llvm/llvm-project/pull/211768
b630323 dropped the cc1-level ImpliedByAnyOf<[cl_fast_relaxed_math]> on fast_math to let -fhonor-nans/-fhonor-infinities override -cl-fast-relaxed-math via the Driver. This broke our downstream test that talks to cc1/CompilerInvocation directly: a bare -cl-fast-relaxed-math no longer implied nnan/ninf/nofpclass, silently degrading to plain contract.
Restore the cc1-level implication so -cl-fast-relaxed-math alone gives the full fast-math cascade again, and give -menable-no-nans/ -menable-no-infs real CC1Option negation flags (-mno-enable-no-nans/ -mno-enable-no-infs). The Driver now emits the negation flag when -fhonor-nans/-fhonor-infinities is combined with -cl-fast-relaxed-math, explicitly cancelling just the implied NaN or Inf assumption without suppressing the rest of the cascade.
>From 152618ca703ffb290e7b0796af0f06431a9b013b Mon Sep 17 00:00:00 2001
From: Wenju He <wenju.he at intel.com>
Date: Fri, 24 Jul 2026 12:49:14 +0200
Subject: [PATCH] [clang][Driver] Restore -cl-fast-relaxed-math fast-math
cascade at cc1 level
b630323 dropped the cc1-level ImpliedByAnyOf<[cl_fast_relaxed_math]> on
fast_math to let -fhonor-nans/-fhonor-infinities override
-cl-fast-relaxed-math via the Driver. This broke our downstream test that
talks to cc1/CompilerInvocation directly: a bare -cl-fast-relaxed-math no
longer implied nnan/ninf/nofpclass, silently degrading to plain contract.
Restore the cc1-level implication so -cl-fast-relaxed-math alone gives
the full fast-math cascade again, and give -menable-no-nans/
-menable-no-infs real CC1Option negation flags (-mno-enable-no-nans/
-mno-enable-no-infs). The Driver now emits the negation flag when
-fhonor-nans/-fhonor-infinities is combined with -cl-fast-relaxed-math,
explicitly cancelling just the implied NaN or Inf assumption without
suppressing the rest of the cascade.
Co-Authored-By: Claude Sonnet 5 <noreply at anthropic.com>
---
clang/include/clang/Options/Options.td | 21 ++++++++++++++-------
clang/lib/Driver/ToolChains/Clang.cpp | 12 ++++++++++++
clang/test/CodeGenOpenCL/relaxed-fpmath.cl | 10 ++++++++++
clang/test/Driver/opencl.cl | 10 +++++++---
4 files changed, 43 insertions(+), 10 deletions(-)
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 41848b18f2e1b..82ba02e262b0c 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2507,7 +2507,8 @@ def ffp_exception_behavior_EQ : Joined<["-"], "ffp-exception-behavior=">, Group<
defm fast_math : BoolFOption<"fast-math",
LangOpts<"FastMath">, Default<hlsl.KeyPath>,
PosFlag<SetTrue, [], [ClangOption, CC1Option, FC1Option, FlangOption],
- "Allow aggressive, lossy floating-point optimizations">,
+ "Allow aggressive, lossy floating-point optimizations",
+ [cl_fast_relaxed_math.KeyPath]>,
NegFlag<SetFalse, [], [ClangOption, CC1Option, FC1Option, FlangOption]>>;
defm math_errno : BoolFOption<"math-errno",
LangOpts<"MathErrno">, DefaultFalse,
@@ -8773,12 +8774,18 @@ let Visibility = [CC1Option, FC1Option] in {
def mreassociate : Flag<["-"], "mreassociate">,
HelpText<"Allow reassociation transformations for floating-point instructions">,
MarshallingInfoFlag<LangOpts<"AllowFPReassoc">>, ImpliedByAnyOf<[funsafe_math_optimizations.KeyPath]>;
-def menable_no_nans : Flag<["-"], "menable-no-nans">,
- HelpText<"Allow optimization to assume there are no NaNs.">,
- MarshallingInfoFlag<LangOpts<"NoHonorNaNs">>, ImpliedByAnyOf<[ffast_math.KeyPath]>;
-def menable_no_infs : Flag<["-"], "menable-no-infs">,
- HelpText<"Allow optimization to assume there are no infinities.">,
- MarshallingInfoFlag<LangOpts<"NoHonorInfs">>, ImpliedByAnyOf<[ffast_math.KeyPath]>;
+defm enable_no_nans : BoolMOption<"enable-no-nans",
+ LangOpts<"NoHonorNaNs">, DefaultFalse,
+ PosFlag<SetTrue, [], [CC1Option, FC1Option],
+ "Allow optimization to assume there are no NaNs.",
+ [ffast_math.KeyPath]>,
+ NegFlag<SetFalse, [], [CC1Option, FC1Option]>>;
+defm enable_no_infs : BoolMOption<"enable-no-infs",
+ LangOpts<"NoHonorInfs">, DefaultFalse,
+ PosFlag<SetTrue, [], [CC1Option, FC1Option],
+ "Allow optimization to assume there are no infinities.",
+ [ffast_math.KeyPath]>,
+ NegFlag<SetFalse, [], [CC1Option, FC1Option]>>;
def pic_level : Separate<["-"], "pic-level">,
HelpText<"Value for __PIC__">,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 660e61d7c5de3..d27d019c88c71 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -3386,11 +3386,23 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
A->claim();
}
+ // -cl-fast-relaxed-math implies -ffast-math at the cc1 level (so that
+ // callers talking to cc1 directly, e.g. via CompilerInvocation, get the
+ // full fast-math cascade from a bare -cl-fast-relaxed-math). When the
+ // Driver determines NaNs/Infs should still be honored (because
+ // -fhonor-nans/-fhonor-infinities overrode -cl-fast-relaxed-math), it must
+ // explicitly cancel that cc1-level implication.
+ bool NeedsHonorOverride = Args.hasArg(options::OPT_cl_fast_relaxed_math);
+
if (!HonorINFs)
CmdArgs.push_back("-menable-no-infs");
+ else if (NeedsHonorOverride)
+ CmdArgs.push_back("-mno-enable-no-infs");
if (!HonorNaNs)
CmdArgs.push_back("-menable-no-nans");
+ else if (NeedsHonorOverride)
+ CmdArgs.push_back("-mno-enable-no-nans");
if (ApproxFunc)
CmdArgs.push_back("-fapprox-func");
diff --git a/clang/test/CodeGenOpenCL/relaxed-fpmath.cl b/clang/test/CodeGenOpenCL/relaxed-fpmath.cl
index e875a6c9d1ad8..44fc9513b5498 100644
--- a/clang/test/CodeGenOpenCL/relaxed-fpmath.cl
+++ b/clang/test/CodeGenOpenCL/relaxed-fpmath.cl
@@ -5,6 +5,14 @@
// RUN: %clang_cc1 %s -emit-llvm -cl-mad-enable -o - | FileCheck %s -check-prefix=MAD
// RUN: %clang_cc1 %s -emit-llvm -cl-no-signed-zeros -o - | FileCheck %s -check-prefix=NOSIGNED
+// -cl-fast-relaxed-math alone implies -ffast-math at the cc1 level, so both
+// -menable-no-nans and -menable-no-infs are implied.
+// RUN: %clang_cc1 %s -emit-llvm -cl-fast-relaxed-math -o - | FileCheck %s -check-prefix=FAST
+// A caller (e.g. a cc1-direct invocation) can cancel just one side of the
+// implied fast-math NaN/Inf assumptions via the negation flags.
+// RUN: %clang_cc1 %s -emit-llvm -cl-fast-relaxed-math -mno-enable-no-nans -o - | FileCheck %s -check-prefix=NONAN
+// RUN: %clang_cc1 %s -emit-llvm -cl-fast-relaxed-math -mno-enable-no-infs -o - | FileCheck %s -check-prefix=NOINF
+
// Check the fp options are correct with PCH.
// RUN: %clang_cc1 %s -DGEN_PCH=1 -finclude-default-header -triple spir-unknown-unknown -emit-pch -o %t.pch
// RUN: %clang_cc1 %s -include-pch %t.pch -fno-validate-pch -emit-llvm -o - | FileCheck %s -check-prefix=NORMAL
@@ -25,6 +33,8 @@ float spscalardiv(float a, float b) {
// UNSAFE: fdiv reassoc nsz arcp contract afn float
// MAD: fdiv float
// NOSIGNED: fdiv nsz float
+ // NONAN: fdiv reassoc ninf nsz arcp contract afn float
+ // NOINF: fdiv reassoc nnan nsz arcp contract afn float
return a / b;
}
// CHECK: attributes
diff --git a/clang/test/Driver/opencl.cl b/clang/test/Driver/opencl.cl
index 8024c27f69f69..3110fb3f0bd77 100644
--- a/clang/test/Driver/opencl.cl
+++ b/clang/test/Driver/opencl.cl
@@ -12,9 +12,9 @@
// RUN: %clang -S -### -cl-finite-math-only %s 2>&1 | FileCheck --check-prefix=CHECK-FINITE-MATH-ONLY %s
// RUN: %clang -S -### -cl-kernel-arg-info %s 2>&1 | FileCheck --check-prefix=CHECK-KERNEL-ARG-INFO %s
// RUN: %clang -S -### -cl-unsafe-math-optimizations %s 2>&1 | FileCheck --check-prefix=CHECK-UNSAFE-MATH-OPT %s
-// RUN: %clang -S -### -cl-fast-relaxed-math %s 2>&1 | FileCheck --check-prefix=CHECK-FAST-RELAXED-MATH %s
-// RUN: %clang -S -### -cl-fast-relaxed-math -fhonor-nans %s 2>&1 | FileCheck --check-prefixes=CHECK-FAST-RELAXED-MATH,NO-NNAN %s
-// RUN: %clang -S -### -cl-fast-relaxed-math -fhonor-infinities %s 2>&1 | FileCheck --check-prefixes=CHECK-FAST-RELAXED-MATH,NO-NINF %s
+// RUN: %clang -S -### -cl-fast-relaxed-math %s 2>&1 | FileCheck --check-prefixes=CHECK-FAST-RELAXED-MATH,NO-MNO-ENABLE %s
+// RUN: %clang -S -### -cl-fast-relaxed-math -fhonor-nans %s 2>&1 | FileCheck --check-prefixes=CHECK-FAST-RELAXED-MATH,NO-NNAN,YES-NO-ENABLE-NNAN %s
+// RUN: %clang -S -### -cl-fast-relaxed-math -fhonor-infinities %s 2>&1 | FileCheck --check-prefixes=CHECK-FAST-RELAXED-MATH,NO-NINF,YES-NO-ENABLE-NINF %s
// RUN: %clang -S -### -cl-mad-enable %s 2>&1 | FileCheck --check-prefix=CHECK-MAD-ENABLE %s
// RUN: %clang -S -### -cl-no-signed-zeros %s 2>&1 | FileCheck --check-prefix=CHECK-NO-SIGNED-ZEROS %s
// RUN: %clang -S -### -cl-denorms-are-zero %s 2>&1 | FileCheck --check-prefix=CHECK-DENORMS-ARE-ZERO %s
@@ -47,6 +47,10 @@
// CHECK-NO-SIGNED-ZEROS: "-cc1" {{.*}} "-cl-no-signed-zeros"
// NO-NNAN-NOT: "menable-no-nans"
// NO-NINF-NOT: "menable-no-infs"
+// YES-NO-ENABLE-NNAN: "-mno-enable-no-nans"
+// YES-NO-ENABLE-NINF: "-mno-enable-no-infs"
+// NO-MNO-ENABLE-NOT: "-mno-enable-no-nans"
+// NO-MNO-ENABLE-NOT: "-mno-enable-no-infs"
// This is not forwarded
// CHECK-DENORMS-ARE-ZERO-NOT: "-cl-denorms-are-zero"
More information about the cfe-commits
mailing list