Skip to content

Disable FTZ/DAZ when compiling shared libraries by default. #80475

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,16 @@ Non-comprehensive list of changes in this release
- ``__typeof_unqual__`` is available in all C modes as an extension, which behaves
like ``typeof_unqual`` from C23, similar to ``__typeof__`` and ``typeof``.


* Shared libraries linked with either the ``-ffast-math``, ``-Ofast``, or
``-funsafe-math-optimizations`` flags will no longer enable flush-to-zero
floating-point mode by default. This decision can be overridden with use of
``-mdaz-ftz``. This behavior now matches GCC's behavior.
(`#57589 <https://github.com/llvm/llvm-project/issues/57589>`_)

* ``-fdenormal-fp-math=preserve-sign`` is no longer implied by ``-ffast-math``
on x86 systems.

New Compiler Flags
------------------
- ``-fsanitize=implicit-bitfield-conversion`` checks implicit truncation and
Expand Down
15 changes: 10 additions & 5 deletions clang/docs/UsersManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1506,7 +1506,8 @@ floating point semantic models: precise (the default), strict, and fast.

* ``-ffp-contract=fast``

Note: ``-ffast-math`` causes ``crtfastmath.o`` to be linked with code. See
Note: ``-ffast-math`` causes ``crtfastmath.o`` to be linked with code unless
``-shared`` or ``-mno-daz-ftz`` is present. See
:ref:`crtfastmath.o` for more details.

.. option:: -fno-fast-math
Expand Down Expand Up @@ -1560,7 +1561,8 @@ floating point semantic models: precise (the default), strict, and fast.
``-ffp-contract``.

Note: ``-fno-fast-math`` implies ``-fdenormal-fp-math=ieee``.
``-fno-fast-math`` causes ``crtfastmath.o`` to not be linked with code.
``-fno-fast-math`` causes ``crtfastmath.o`` to not be linked with code
unless ``-mdaz-ftz`` is present.

.. option:: -fdenormal-fp-math=<value>

Expand Down Expand Up @@ -1938,10 +1940,13 @@ by using ``#pragma STDC FENV_ROUND`` with a value other than ``FE_DYNAMIC``.

A note about ``crtfastmath.o``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
``-ffast-math`` and ``-funsafe-math-optimizations`` cause ``crtfastmath.o`` to be
automatically linked, which adds a static constructor that sets the FTZ/DAZ
``-ffast-math`` and ``-funsafe-math-optimizations`` without the ``-shared``
option cause ``crtfastmath.o`` to be
automatically linked, which adds a static constructor that sets the FTZ/DAZ
bits in MXCSR, affecting not only the current compilation unit but all static
and shared libraries included in the program.
and shared libraries included in the program. This decision can be overridden
by using either the flag ``-mdaz-ftz`` or ``-mno-daz-ftz`` to respectively
link or not link ``crtfastmath.o``.

.. _FLT_EVAL_METHOD:

Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -2615,6 +2615,11 @@ defm protect_parens : BoolFOption<"protect-parens",
"floating-point expressions are evaluated">,
NegFlag<SetFalse>>;

defm daz_ftz : SimpleMFlag<"daz-ftz",
"Globally set", "Do not globally set",
" the denormals-are-zero (DAZ) and flush-to-zero (FTZ) bits in the "
"floating-point control register on program startup">;

def ffor_scope : Flag<["-"], "ffor-scope">, Group<f_Group>;
def fno_for_scope : Flag<["-"], "fno-for-scope">, Group<f_Group>;

Expand Down
15 changes: 13 additions & 2 deletions clang/lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1307,9 +1307,14 @@ void ToolChain::AddCCKextLibArgs(const ArgList &Args,

bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args,
std::string &Path) const {
// Don't implicitly link in mode-changing libraries in a shared library, since
// this can have very deleterious effects. See the various links from
// https://github.com/llvm/llvm-project/issues/57589 for more information.
bool Default = !Args.hasArgNoClaim(options::OPT_shared);

// Do not check for -fno-fast-math or -fno-unsafe-math when -Ofast passed
// (to keep the linker options consistent with gcc and clang itself).
if (!isOptimizationLevelFast(Args)) {
if (Default && !isOptimizationLevelFast(Args)) {
// Check if -ffast-math or -funsafe-math.
Arg *A =
Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math,
Expand All @@ -1318,8 +1323,14 @@ bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args,

if (!A || A->getOption().getID() == options::OPT_fno_fast_math ||
A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations)
return false;
Default = false;
}

// Whatever decision came as a result of the above implicit settings, either
// -mdaz-ftz or -mno-daz-ftz is capable of overriding it.
if (!Args.hasFlag(options::OPT_mdaz_ftz, options::OPT_mno_daz_ftz, Default))
return false;

// If crtfastmath.o exists add it to the arguments.
Path = GetFilePath("crtfastmath.o");
return (Path != "crtfastmath.o"); // Not found.
Expand Down
19 changes: 0 additions & 19 deletions clang/lib/Driver/ToolChains/Linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -842,25 +842,6 @@ void Linux::addProfileRTLibs(const llvm::opt::ArgList &Args,
ToolChain::addProfileRTLibs(Args, CmdArgs);
}

llvm::DenormalMode
Linux::getDefaultDenormalModeForType(const llvm::opt::ArgList &DriverArgs,
const JobAction &JA,
const llvm::fltSemantics *FPType) const {
switch (getTriple().getArch()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should shared libraries be using dynamic mode?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably. But we can't reliably tell from the individual file compile commands if we're going to be linked as a shared library or not, which is why I'm dropping this attempt to set it at all in the first place.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So getDefaultDenormalModeForType() in ToolChain.h should be returning DenormalMode::Dynamic() rather than DenormalMode::getIEEE(), right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we shouldn't. This was discussed before: #80475 (comment) and surrounding comments.
But in short: doing so would regress normal code, only for the (arguable) benefit of code which is explicitly asks to play fast-and-loose with the rules via -ffast-math.

I think the change is good as-is.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't think that had been resolved, but I agree that this change is good as-is.

It's not just fast-math that can change ftz/daz though. Users can also modify MXCSR directly. In C, FENV_ACCESS needs to be enabled, but in practice I find that users would like to be able to do that without taking on the other penalties associated with enabling fenv access (such as generally diminished optimization). It would be nice if LLVM IR had a way to allow this.

case llvm::Triple::x86:
case llvm::Triple::x86_64: {
std::string Unused;
// DAZ and FTZ are turned on in crtfastmath.o
if (!DriverArgs.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
isFastMathRuntimeAvailable(DriverArgs, Unused))
return llvm::DenormalMode::getPreserveSign();
return llvm::DenormalMode::getIEEE();
}
default:
return llvm::DenormalMode::getIEEE();
}
}

void Linux::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const {
for (const auto &Opt : ExtraOpts)
CmdArgs.push_back(Opt.c_str());
Expand Down
4 changes: 0 additions & 4 deletions clang/lib/Driver/ToolChains/Linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,6 @@ class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF {

std::vector<std::string> ExtraOpts;

llvm::DenormalMode getDefaultDenormalModeForType(
const llvm::opt::ArgList &DriverArgs, const JobAction &JA,
const llvm::fltSemantics *FPType = nullptr) const override;

const char *getDefaultLinker() const override;

protected:
Expand Down
9 changes: 0 additions & 9 deletions clang/test/Driver/default-denormal-fp-math.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,6 @@

// RUN: %clang -### -target x86_64-unknown-linux-gnu --sysroot=%S/Inputs/basic_linux_tree -c %s -v 2>&1 | FileCheck -check-prefix=CHECK-IEEE %s

// crtfastmath enables ftz and daz
// RUN: %clang -### -target x86_64-unknown-linux-gnu -ffast-math --sysroot=%S/Inputs/basic_linux_tree -c %s -v 2>&1 | FileCheck -check-prefix=CHECK-PRESERVESIGN %s

// crt not linked in with nostartfiles
// RUN: %clang -### -target x86_64-unknown-linux-gnu -ffast-math -nostartfiles --sysroot=%S/Inputs/basic_linux_tree -c %s -v 2>&1 | FileCheck -check-prefix=CHECK-IEEE %s

// If there's no crtfastmath, don't assume ftz/daz
// RUN: %clang -### -target x86_64-unknown-linux-gnu -ffast-math --sysroot=/dev/null -c %s -v 2>&1 | FileCheck -check-prefix=CHECK-IEEE %s

// RUN: %clang -### -target x86_64-scei-ps4 -c %s -v 2>&1 | FileCheck -check-prefix=CHECK-PRESERVESIGN %s

// Flag omitted for default
Expand Down
26 changes: 26 additions & 0 deletions clang/test/Driver/linux-ld.c
Original file line number Diff line number Diff line change
Expand Up @@ -1446,6 +1446,32 @@
// RUN: %clang --target=i386-unknown-linux -no-pie -### %s -ffast-math \
// RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH %s
// Don't link crtfastmath.o with -shared
// RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -ffast-math -shared \
// RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH %s
// RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -Ofast -shared \
// RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH %s
// Check for effects of -mdaz-ftz
// RUN: %clang --target=x86_64-unknown-linux -### %s -ffast-math -shared -mdaz-ftz \
// RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s
// RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -ffast-math -mdaz-ftz \
// RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s
// RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -mdaz-ftz \
// RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s
// RUN: %clang --target=x86_64-unknown-linux -### %s -ffast-math -shared -mno-daz-ftz \
// RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH %s
// RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -ffast-math -mno-daz-ftz \
// RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH %s
// RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -mno-daz-ftz \
// RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH %s
// CHECK-CRTFASTMATH: usr/lib/gcc/x86_64-unknown-linux/10.2.0{{/|\\\\}}crtfastmath.o
// CHECK-NOCRTFASTMATH-NOT: crtfastmath.o

Expand Down