From f9e28ce4602aff3f9bb4e743b0d6167b0f8df88d Mon Sep 17 00:00:00 2001 From: AKhatskevich <avkhatskevich@tarantool.org> Date: Thu, 22 Mar 2018 11:37:06 +0300 Subject: [PATCH] Add LTO support Added -DENABLE_LTO=ON/OFF cmake option, OFF by default. LTO speeds up cpu-intensive workloads by up to 20% (see [1] and [2]). Requirements to enable LTO: - cmake >= 3.9; - Linux: ld.bfd / ld.gold from binutils >= 2.31 (or later 2.30) (gold >= 1.15); - Mac OS: xcode >= 8 (earlier versions are not tested). The requirement of the recent ld version is due to bug with exporting symbols from dynamic list when LTO is enabled, see [3]. Note: -Wlto-type-mismatch on GCC (enabled by default with -flto) gives namy warnings. Filed [4] to investigate it. Note: LuaJIT will be compiled w/o LTO despite the option set, filed [5]. [1]: https://github.com/tarantool/tarantool/wiki/performance-research [2]: https://gist.github.com/Khatskevich/31a2da6ab46ce903120e7a03d65966db [3]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84901 [4]: https://github.com/tarantool/tarantool/issues/3742 [5]: https://github.com/tarantool/tarantool/issues/3743 Closes #3117 f --- CMakeLists.txt | 3 ++ cmake/lto.cmake | 97 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 cmake/lto.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 439a2750a6..491ccaf0b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,6 +63,9 @@ include(cmake/pod2man.cmake) include(cmake/arch.cmake) include(cmake/os.cmake) include(cmake/compiler.cmake) +# NO_POLICY_SCOPE is to suppress CMP0069 warnings on the unset +# policy. +include(cmake/lto.cmake NO_POLICY_SCOPE) include(cmake/simd.cmake) include(cmake/atomic.cmake) include(cmake/profile.cmake) diff --git a/cmake/lto.cmake b/cmake/lto.cmake new file mode 100644 index 0000000000..95ade75f48 --- /dev/null +++ b/cmake/lto.cmake @@ -0,0 +1,97 @@ +# +# Manage LTO (Link-Time-Optimization) and IPO +# (Inter-Procedural-Optimization) +# + +# Tarantool uses both dynamic-list and lto link options, which +# works only since binutils: +# +# - 2.30 for linking with ld.gold (gold version is 1.15); +# - last 2.30 or 2.31 in case of ld.bfd. + +# This cmake module exports CMP0069 policy and should be included +# with NO_POLICY_SCOPE option. + +# The file gives an error if LTO is requested, but cannot be +# enabled for some reason. + +if (NOT DEFINED ENABLE_LTO) + set(ENABLE_LTO OFF) +endif() + +# Disable LTO if not requested. +if (NOT ENABLE_LTO) + message(STATUS "Enabling LTO: FALSE") + return() +endif() + +if(CMAKE_VERSION VERSION_LESS 3.9) + message(FATAL_ERROR "cmake >= 3.9 is needed to enable LTO") +endif() + +# 'CMP0069 NEW' behaviour enables LTO for compilers other then +# Intel Compiler when CMAKE_INTERPROCEDURAL_OPTIMIZATION is +# enabled and provides CheckIPOSupported module. We set the policy +# to support LTO with GCC / Clang and to suppress cmake warnings +# on the unset policy. +cmake_policy(SET CMP0069 NEW) + +# Retain 'CMP0069 NEW' behaviour after +# 'cmake_minimum_required(VERSION ...) in subprojects to +# avoid cmake warnings on the unset policy. +set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) + +# Check whether LTO is supported by the compiler / toolchain and +# give an error otherwise. +include(CheckIPOSupported) +check_ipo_supported(RESULT CMAKE_IPO_AVAILABLE) +if (NOT CMAKE_IPO_AVAILABLE) + message(FATAL_ERROR "LTO is not supported by the compiler / toolchain") +endif() + +# Extra checks on Linux whether all needed LTO features are +# supported. Mac OS seems to work correctly with xcode >= 8. +if (NOT TARGET_OS_DARWIN) + execute_process( + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND ld -v OUTPUT_VARIABLE linker_version_str) + message(STATUS "ld version string: ${linker_version_str}") + + # GNU ld (Gentoo 2.31.1 p3) 2.31.1 + # GNU ld (GNU Binutils for Ubuntu) 2.30 + # GNU ld version 2.27-10.el7 + string(REGEX MATCH "^GNU ld.* (2\\.[0-9]+)[^ ]*$" matched_bfd + ${linker_version_str}) + + # GNU gold (Gentoo 2.31.1 p3 2.31.1) 1.16 + # GNU gold (GNU Binutils for Ubuntu 2.30) 1.15 + # GNU gold (version 2.27-10.el7) 1.12 + if (NOT matched_bfd) + string(REGEX MATCH "^GNU gold.* (1\\.[0-9]+)[^ ]*$" matched_gold + ${linker_version_str}) + endif() + + if(matched_bfd) + set(linker_version ${CMAKE_MATCH_1}) + message(STATUS "Found ld.bfd version: ${linker_version}") + + if (linker_version VERSION_LESS "2.31") + message(FATAL_ERROR "ld.bfd >= 2.31 is needed for LTO") + endif() + elseif(matched_gold) + set(linker_version ${CMAKE_MATCH_1}) + message(STATUS "Found ld.gold version: ${linker_version}") + + if (linker_version VERSION_LESS "1.15") + message(FATAL_ERROR "ld.gold >= 1.15 is needed for LTO") + endif() + else() + message(FATAL_ERROR "Unsupported ld version format") + endif() +endif() + +# gh-3742: investigate LTO warnings. +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wno-lto-type-mismatch") + +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) +message(STATUS "Enabling LTO: TRUE") -- GitLab