diff --git a/.appveyor.yml b/.appveyor.yml index d55826f4..d44067de 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -53,7 +53,6 @@ build_script: cmake -Wdev -G"%generator%" -A"%platform%" -S. -Bbuild -DCMAKE_CONFIGURATION_TYPES=Release -DBUILD_CRUNCH=ON -DBUILD_EXAMPLES=ON - -DUSE_FAST_MATH=OFF cmake --build build --config Release diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 9b4a9a98..c22b05ef 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -125,7 +125,6 @@ steps: if [ -z "${SOURCE_DIR:-}" ]; then cmake_args+=(-DBUILD_CRUNCH=ON -DBUILD_EXAMPLES=ON -DBUILD_SHARED_LIBS=ON) fi - cmake_args+=(-DUSE_FAST_MATH=OFF) cmake -S"${SOURCE_DIR:-.}" -Bbuild "${cmake_args[@]}" cmake --build build --config Release displayName: 'Build' diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ed79c99..4ba54dd0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 11) +include(CheckCXXCompilerFlag) + set(CRUNCH_PROJECT_NAME crunch) set(CRUNCH_LIBRARY_NAME crn) set(CRUNCH_EXE_NAME crunch) @@ -50,10 +52,18 @@ macro(set_linker_flag FLAG) endif() endmacro() +macro(try_cxx_flag PROP FLAG) + check_CXX_compiler_flag(${FLAG} FLAG_${PROP}) + + if (FLAG_${PROP}) + set_cxx_flag(${FLAG}) + endif() +endmacro() + # This option decides if crunch is dynamically linked against libcrn.so # statically linked against libcrn.o, enabling it always build libcrn.so. # This option is a builtin CMake one, the name means “build executables -# against shader libraries”, not “build the shared libraries”. +# against shared libraries”, not “build the shared libraries”. option(BUILD_SHARED_LIBS "Link executables against shared library" OFF) # Always build libcrn.so even if crunch is linked to libcrn statically. option(BUILD_SHARED_LIBCRN "Build shared libcrn" OFF) @@ -85,6 +95,9 @@ if (MSVC) # and https://devblogs.microsoft.com/cppblog/the-fpcontract-flag-and-changes-to-fp-modes-in-vs2022/ # By default, MSVC doesn't enable the /fp:fast option. set_cxx_flag("/fp:fast") + else() + # Precise model (/fp:precise) should do safe contractions, but we should not trust that (see below). + set_cxx_flag("/fp:strict") endif() if (USE_LTO) @@ -112,22 +125,45 @@ else() set_cxx_flag("-O3" RELWITHDEBINFO) endif() + try_cxx_flag(FNO_MATH_ERRNO "-fno-math-errno") + if (USE_FAST_MATH) - # By default, GCC uses -ffp-contract=fast with -std=gnu* and uses -ffp-contract=off with -std=c*. - # See https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html - # By default, GCC doesn't enable the -ffast-math option. - set_cxx_flag("-ffast-math -fno-math-errno -ffp-contract=fast") + try_cxx_flag(FFAST_MATH "-ffast-math") + + # GCC. + try_cxx_flag(FFP_CONTRACT_FAST "-ffp-contract=fast") + # Clang. + try_cxx_flag(FFP_MODEL_FAST "-ffp-model=agressive") + # ICC. + try_cxx_flag(FP_MODEL_FAST_2 "-fp-model=fast=2") + try_cxx_flag(QSIMD_HONOR_FP_MODEL "-qsimd-honor-fp-model") else() + try_cxx_flag(FNO_FAST_MATH "-fno-fast-math") + + # By default, GCC uses -ffp-contract=fast with -std=gnu* and uses -ffp-contract=off with -std=c*. # By default, GCC uses -std=gnu* and then enables -ffp-contract=fast even if -ffast-math is not enabled. - set_cxx_flag("-ffp-contract=off") + # See https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html + # GCC fast contractions (-ffp-contract=fast) should be safe, but aren't on arm64 with GCC 12. + # Clang precise contractions (-ffp-contract=precise) should be safe, but aren't on arm64 with Clang 14. + + # GCC. + try_cxx_flag(FFP_CONTRACT_OFF "-ffp-contract=off") + # Clang + try_cxx_flag(FFP_MODEL_STRICT "-ffp-model=strict") + # ICC. + try_cxx_flag(FP_MODEL_STRICT "-fp-model=strict") + try_cxx_flag(QSIMD_HONOR_FP_MODEL "-qsimd-honor-fp-model") endif() # It should be done at the very end because it copies all compiler flags # to the linker flags. if (USE_LTO) - set_cxx_flag("-flto" RELEASE) - set_cxx_flag("-flto" RELWITHDEBINFO) - set_cxx_flag("-flto" MINSIZEREL) + try_cxx_flag(FLTO_AUTO "-flto=auto") + + if (NOT FLAG_FLTO_AUTO) + try_cxx_flag(FLTO "-flto") + endif() + set_linker_flag("${CMAKE_CXX_FLAGS}" RELEASE) set_linker_flag("${CMAKE_CXX_FLAGS}" RELWITHDEBINFO) set_linker_flag("${CMAKE_CXX_FLAGS}" MINSIZEREL)