Index: clang/include/clang/Driver/ToolChain.h =================================================================== --- clang/include/clang/Driver/ToolChain.h +++ clang/include/clang/Driver/ToolChain.h @@ -573,12 +573,19 @@ virtual void AddCCKextLibArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; + /// If a runtime library exists that sets global flags for unsafe floating + /// point math, return true. + /// + /// This checks for presence of the -Ofast, -ffast-math or -funsafe-math flags. + virtual bool isFastMathRuntimeAvailable( + const llvm::opt::ArgList &Args, std::string &Path) const; + /// AddFastMathRuntimeIfAvailable - If a runtime library exists that sets /// global flags for unsafe floating point math, add it and return true. /// /// This checks for presence of the -Ofast, -ffast-math or -funsafe-math flags. - virtual bool AddFastMathRuntimeIfAvailable( - const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; + bool addFastMathRuntimeIfAvailable( + const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; /// addProfileRTLibs - When -fprofile-instr-profile is specified, try to pass /// a suitable profile runtime library to the linker. Index: clang/lib/Driver/ToolChain.cpp =================================================================== --- clang/lib/Driver/ToolChain.cpp +++ clang/lib/Driver/ToolChain.cpp @@ -917,28 +917,35 @@ CmdArgs.push_back("-lcc_kext"); } -bool ToolChain::AddFastMathRuntimeIfAvailable(const ArgList &Args, - ArgStringList &CmdArgs) const { +bool ToolChain::isFastMathRuntimeAvailable(const ArgList &Args, + std::string &Path) const { // 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)) { // Check if -ffast-math or -funsafe-math. Arg *A = - Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math, - options::OPT_funsafe_math_optimizations, - options::OPT_fno_unsafe_math_optimizations); + Args.getLastArg(options::OPT_ffast_math, options::OPT_fno_fast_math, + options::OPT_funsafe_math_optimizations, + options::OPT_fno_unsafe_math_optimizations); if (!A || A->getOption().getID() == options::OPT_fno_fast_math || A->getOption().getID() == options::OPT_fno_unsafe_math_optimizations) return false; } // If crtfastmath.o exists add it to the arguments. - std::string Path = GetFilePath("crtfastmath.o"); - if (Path == "crtfastmath.o") // Not found. - return false; + Path = GetFilePath("crtfastmath.o"); + return (Path != "crtfastmath.o"); // Not found. +} + +bool ToolChain::addFastMathRuntimeIfAvailable(const ArgList &Args, + ArgStringList &CmdArgs) const { + std::string Path; + if (isFastMathRuntimeAvailable(Args, Path)) { + CmdArgs.push_back(Args.MakeArgString(Path)); + return true; + } - CmdArgs.push_back(Args.MakeArgString(Path)); - return true; + return false; } SanitizerMask ToolChain::getSupportedSanitizers() const { Index: clang/lib/Driver/ToolChains/Gnu.cpp =================================================================== --- clang/lib/Driver/ToolChains/Gnu.cpp +++ clang/lib/Driver/ToolChains/Gnu.cpp @@ -502,7 +502,7 @@ } // Add crtfastmath.o if available and fast math is enabled. - ToolChain.AddFastMathRuntimeIfAvailable(Args, CmdArgs); + ToolChain.addFastMathRuntimeIfAvailable(Args, CmdArgs); } Args.AddAllArgs(CmdArgs, options::OPT_L); Index: clang/lib/Driver/ToolChains/Linux.h =================================================================== --- clang/lib/Driver/ToolChains/Linux.h +++ clang/lib/Driver/ToolChains/Linux.h @@ -46,6 +46,11 @@ std::vector ExtraOpts; + llvm::DenormalMode getDefaultDenormalModeForType( + const llvm::opt::ArgList &DriverArgs, + Action::OffloadKind DeviceOffloadKind, + const llvm::fltSemantics *FPType = nullptr) const override; + protected: Tool *buildAssembler() const override; Tool *buildLinker() const override; Index: clang/lib/Driver/ToolChains/Linux.cpp =================================================================== --- clang/lib/Driver/ToolChains/Linux.cpp +++ clang/lib/Driver/ToolChains/Linux.cpp @@ -988,3 +988,22 @@ Twine("-u", llvm::getInstrProfRuntimeHookVarName()))); ToolChain::addProfileRTLibs(Args, CmdArgs); } + +llvm::DenormalMode Linux::getDefaultDenormalModeForType( + const llvm::opt::ArgList &DriverArgs, + Action::OffloadKind DeviceOffloadKind, + const llvm::fltSemantics *FPType) const { + switch (getTriple().getArch()) { + 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(); + } +} Index: clang/lib/Driver/ToolChains/MinGW.cpp =================================================================== --- clang/lib/Driver/ToolChains/MinGW.cpp +++ clang/lib/Driver/ToolChains/MinGW.cpp @@ -300,7 +300,7 @@ if (!Args.hasArg(options::OPT_nostartfiles)) { // Add crtfastmath.o if available and fast math is enabled. - TC.AddFastMathRuntimeIfAvailable(Args, CmdArgs); + TC.addFastMathRuntimeIfAvailable(Args, CmdArgs); CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o"))); } Index: clang/lib/Driver/ToolChains/PS4CPU.h =================================================================== --- clang/lib/Driver/ToolChains/PS4CPU.h +++ clang/lib/Driver/ToolChains/PS4CPU.h @@ -88,6 +88,14 @@ // capable of unit splitting. bool canSplitThinLTOUnit() const override { return false; } + llvm::DenormalMode getDefaultDenormalModeForType( + const llvm::opt::ArgList &DriverArgs, + Action::OffloadKind DeviceOffloadKind, + const llvm::fltSemantics *FPType) const override { + // DAZ and FTZ are on by default. + return llvm::DenormalMode::getPreserveSign(); + } + protected: Tool *buildAssembler() const override; Tool *buildLinker() const override; Index: clang/test/Driver/default-denormal-fp-math.c =================================================================== --- /dev/null +++ clang/test/Driver/default-denormal-fp-math.c @@ -0,0 +1,19 @@ +// RUN: %clang -### -target arm-unknown-linux-gnu -c %s -v 2>&1 | FileCheck -check-prefix=CHECK-IEEE %s +// RUN: %clang -### -target i386-unknown-linux-gnu -c %s -v 2>&1 | FileCheck -check-prefix=CHECK-IEEE %s + +// 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 + + +// CHECK-IEEE: -fdenormal-fp-math=ieee,ieee +// CHECK-PRESERVESIGN: -fdenormal-fp-math=preserve-sign,preserve-sign