Skip to content

Commit f872ae2

Browse files
committed
added: (advanced) support for LTO in buildsystem
while cmake has a generic CMAKE_INTERPROCEDURAL_OPTIMIZATION flag this is problematic since it uses all cores for each linker job, overwhelming the system when there are many linking stages. so we add our own, mostly "borrowed" from opm-common and simplified, with support for setting the number of jobs and for using LTO cache where available. - -DIFEM_USE_LTO to enable - -DIFEM_LTO_JOBS=x to set number of linker optimization job - -DIFEM_LTO_CONFIGURATION_TYPES=xx to enable for a configuration (defaults to Release and RelWithDebubInfo) - -DIFEM_LTO_CACHE_POLICY to override default lto cache policies
1 parent 791da7f commit f872ae2

File tree

7 files changed

+144
-0
lines changed

7 files changed

+144
-0
lines changed

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ list(APPEND CMAKE_MODULE_PATH
2626

2727
include(IFEMOptions)
2828
include(IFEMBuildTypes)
29+
include(IFEMLTO)
2930

3031
add_library(IFEM)
3132

@@ -38,6 +39,7 @@ set_target_properties(
3839
SOVERSION
3940
${IFEM_ABI_VERSION}
4041
)
42+
ifem_lto(TARGET IFEM)
4143

4244
target_compile_definitions(IFEM PUBLIC $<$<CONFIG:Debug>:INDEX_CHECK=2>)
4345
if(VERBOSE_DEBUG GREATER 0)
@@ -718,6 +720,7 @@ install(
718720
cmake/IFEMAddTargets.cmake
719721
cmake/IFEMDoxy.cmake
720722
cmake/IFEMFindDependencies.cmake
723+
cmake/IFEMLTO.cmake
721724
cmake/IFEMOptionsDownstream.cmake
722725
cmake/IFEMTesting.cmake
723726
cmake/Modules/FindARPACK.cmake

cmake/IFEMAddTargets.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ function(ifem_add_library)
3838
ARCHIVE_OUTPUT_DIRECTORY
3939
${CMAKE_BINARY_DIR}/lib
4040
)
41+
ifem_lto(TARGET ${PARAM_NAME})
4142
ifem_add_sca_tests(TARGET ${PARAM_NAME})
4243
endfunction()
4344

@@ -68,6 +69,7 @@ function(ifem_add_application)
6869
RUNTIME_OUTPUT_DIRECTORY
6970
${CMAKE_BINARY_DIR}/bin
7071
)
72+
ifem_lto(TARGET ${PARAM_NAME})
7173
ifem_add_sca_tests(TARGET ${PARAM_NAME})
7274
list(APPEND TEST_APPS ${PARAM_NAME})
7375
set(TEST_APPS ${TEST_APPS} PARENT_SCOPE)

cmake/IFEMLTO.cmake

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
include(CheckIPOSupported)
2+
include(TestCXXAcceptsFlag)
3+
4+
# ------------------------------------------------------------------------------
5+
# ifem_lto
6+
#
7+
# Configure link-time optimization (IPO) for a target.
8+
#
9+
# This function enables LTO (Link Time Optimization) on the specified target.
10+
# It has extended interfaces for GCC and Clang settings.
11+
#
12+
# Enablement is controlled using the IFEM_USE_LTO option.
13+
#
14+
# Incremental cache directories are automatically managed under:
15+
# ${CMAKE_BINARY_DIR}/LTOCache/<config>
16+
#
17+
# Usage:
18+
#
19+
# ifem_ipo(
20+
# TARGET <target>
21+
# [CONFIGURATION_TYPES <config1;config2;...>]
22+
# )
23+
#
24+
# Arguments:
25+
# TARGET (required) Target to which optimization will be applied.
26+
# CONFIGURATION_TYPES (optional) List of configuration names (e.g. Release).
27+
# If omitted, the default list from:
28+
# IFEM_LTO_CONFIGURATION_TYPES
29+
# is used.
30+
#
31+
# Cache Variables:
32+
# IFEM_LTO_JOBS (e.g. 1, 8)
33+
# IFEM_LTO_CACHE_POLICY (e.g. "prune_after=604800")
34+
# IFEM_LTO_CONFIGURATION_TYPES (e.g. "Release;RelWithDebInfo")
35+
#
36+
# ------------------------------------------------------------------------------
37+
38+
set(IFEM_LTO_CONFIGURATION_TYPES "Release;RelWithDebInfo" CACHE
39+
STRING "Default configuration types to apply interprocedural optimization.")
40+
set(IFEM_LTO_JOBS 1 CACHE STRING "Default interprocedural optimization jobs. Set to 'auto' to use all cores")
41+
set(IFEM_LTO_CACHE_POLICY "" CACHE STRING "Default interprocedural optimization cache policy.")
42+
mark_as_advanced(IFEM_LTO_CACHE_POLICY)
43+
mark_as_advanced(IFEM_LTO_CONFIGURATION_TYPES)
44+
45+
# define possible values for LTO (order matters: first one in the list is used as default type)
46+
set(ifem_ipo_types)
47+
check_ipo_supported(LANGUAGES C CXX RESULT ipo_supported)
48+
49+
if(IFEM_USE_LTO AND NOT ipo_supported)
50+
message(STATUS "Link-time optimization not supported")
51+
set(IFEM_USE_LTO OFF)
52+
endif()
53+
54+
if(IFEM_USE_LTO)
55+
message(STATUS "Link-time optimization enabled")
56+
endif()
57+
58+
function(ifem_lto)
59+
if(NOT IFEM_USE_LTO)
60+
return()
61+
endif()
62+
63+
cmake_parse_arguments(PARAM "" "TARGET" "CONFIGURATION_TYPES" ${ARGN})
64+
65+
# if not set, use the default configuration types
66+
if(NOT PARAM_CONFIGURATION_TYPES)
67+
set(PARAM_CONFIGURATION_TYPES ${IFEM_LTO_CONFIGURATION_TYPES})
68+
endif()
69+
70+
foreach(config ${PARAM_CONFIGURATION_TYPES})
71+
if(CMAKE_CONFIGURATION_TYPES MATCHES ${config} OR CMAKE_BUILD_TYPE MATCHES ${config})
72+
set(LTO_CACHE_PATH ${CMAKE_BINARY_DIR}/LTOCache/${config})
73+
74+
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
75+
# https://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/Optimize-Options.html
76+
target_compile_options(${PARAM_TARGET} PRIVATE $<$<CONFIG:${config}>:-flto=${IFEM_LTO_JOBS}>)
77+
target_link_options(${PARAM_TARGET} INTERFACE $<$<CONFIG:${config}>:-flto=${IFEM_LTO_JOBS}>)
78+
79+
if(CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 15.0.0)
80+
# use incremental LTO https://gcc.gnu.org/onlinedocs/gcc-15.2.0/gcc/Optimize-Options.html
81+
target_compile_options(${PARAM_TARGET} PRIVATE $<$<CONFIG:${config}>:-flto-incremental=${LTO_CACHE_PATH}>)
82+
target_link_options(${PARAM_TARGET} INTERFACE $<$<CONFIG:${config}>:-flto-incremental=${LTO_CACHE_PATH}>)
83+
84+
# Configure cache directory
85+
file(MAKE_DIRECTORY ${LTO_CACHE_PATH})
86+
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_CLEAN_FILES ${LTO_CACHE_PATH})
87+
endif()
88+
elseif(CMAKE_CXX_COMPILER_ID STREQUAL Clang)
89+
# Use ThinLTO and reuse cache (see https://releases.llvm.org/20.1.0/tools/clang/docs/ThinLTO.html)
90+
91+
if(${CMAKE_CXX_COMPILER_LINKER_ID} MATCHES "GNU")
92+
message(FATAL_ERROR "Cannot use ThinLTO with BFD linker")
93+
endif()
94+
95+
target_compile_options(${PARAM_TARGET} PRIVATE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:${config}>>:-flto=thin>)
96+
target_link_options(${PARAM_TARGET} INTERFACE $<$<CONFIG:${config}>:-flto=thin>)
97+
98+
# Configure cache directory
99+
file(MAKE_DIRECTORY ${LTO_CACHE_PATH})
100+
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_CLEAN_FILES ${LTO_CACHE_PATH})
101+
102+
# Parallel and cache options are linker dependent
103+
if(${CMAKE_CXX_COMPILER_LINKER_ID} MATCHES "LLD")
104+
target_link_options(${PARAM_TARGET} INTERFACE
105+
$<$<CONFIG:${config}>:LINKER:--thinlto-jobs=${IFEM_LTO_JOBS}>
106+
$<$<CONFIG:${config}>:LINKER:--thinlto-cache-dir=${LTO_CACHE_PATH}>
107+
)
108+
if(IFEM_LTO_CACHE_POLICY)
109+
target_link_options(${PARAM_TARGET} INTERFACE
110+
$<$<CONFIG:${config}>:LINKER:--thinlto-cache-policy=${IFEM_LTO_CACHE_POLICY}>
111+
)
112+
endif()
113+
elseif(${CMAKE_CXX_COMPILER_LINKER_ID} MATCHES "GNU|GNUgold|MOLD")
114+
target_link_options(${PARAM_TARGET} INTERFACE
115+
$<$<CONFIG:${config}>:LINKER:-plugin-opt,jobs=${IFEM_LTO_JOBS}>
116+
$<$<CONFIG:${config}>:LINKER:-plugin-opt,cache-dir=${LTO_CACHE_PATH}>
117+
)
118+
if(IFEM_LTO_CACHE_POLICY)
119+
target_link_options(${PARAM_TARGET} INTERFACE
120+
$<$<CONFIG:${config}>:LINKER:-plugin-opt,cache-policy=${IFEM_LTO_CACHE_POLICY}>
121+
)
122+
endif()
123+
elseif(${CMAKE_CXX_COMPILER_LINKER_ID} MATCHES "AppleClang")
124+
target_link_options(${PARAM_TARGET} INTERFACE
125+
$<$<CONFIG:${config}>:LINKER:-mllvm,-threads=${IFEM_LTO_JOBS}>
126+
$<$<CONFIG:${config}>:LINKER:-cache_path_lto,${LTO_CACHE_PATH}>
127+
)
128+
else()
129+
message(DEBUG "LTO for Clang is supported, but linker type '${CMAKE_CXX_COMPILER_LINKER_ID}' is unrecognized. Skip adding parallelism or cache flags.")
130+
endif()
131+
endif()
132+
endif()
133+
endforeach()
134+
endfunction()

cmake/IFEMOptions.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ option(IFEM_USE_UMFPACK "Compile with UMFPACK support?" ON)
1515
option(IFEM_USE_CEREAL "Compile with cereal support?" ON)
1616
option(IFEM_USE_ZOLTAN "Compile with zoltan support?" OFF)
1717
option(IFEM_USE_TRACY "Enable tracer profiler?" OFF)
18+
option(IFEM_USE_LTO "Enable link-time optimizoation?" OFF)
1819

1920
set(IFEM_USE_SPR "OFF" CACHE STRING "Compile with SPR support?")
2021
set_property(CACHE IFEM_USE_SPR PROPERTY STRINGS ON I32 I64 OFF)

cmake/IFEMSetupDependencies.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ target_link_libraries(IFEM PUBLIC
1212
${CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES}
1313
)
1414

15+
target_link_directories(IFEM PUBLIC ${CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES})
16+
1517
if(IFEM_USE_SUPERLU OR IFEM_USE_SUPERLU_MT)
1618
if(IFEM_USE_SUPERLU_MT AND TARGET SuperLU::SuperLUMT)
1719
target_link_libraries(IFEM PUBLIC SuperLU::SuperLUMT)

cmake/Templates/IFEMConfig-install.cmake.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
2626
include("${CMAKE_CURRENT_LIST_DIR}/IFEMFindDependencies.cmake")
2727
include("${CMAKE_CURRENT_LIST_DIR}/IFEMOptionsDownstream.cmake")
2828
include("${CMAKE_CURRENT_LIST_DIR}/IFEMTargets.cmake")
29+
include("${CMAKE_CURRENT_LIST_DIR}/IFEMLTO.cmake")
2930
include("${CMAKE_CURRENT_LIST_DIR}/IFEMAddTargets.cmake")
3031
include("${CMAKE_CURRENT_LIST_DIR}/IFEMTesting.cmake")
3132
include("${CMAKE_CURRENT_LIST_DIR}/IFEMDoxy.cmake")

cmake/Templates/IFEMConfig.cmake.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ set(IFEM_PATH @IFEM_PATH@)
2121
list(APPEND CMAKE_MODULE_PATH ${IFEM_PATH}/cmake ${IFEM_PATH}/cmake/Modules)
2222
include(IFEMSetupVariables)
2323
include(IFEMFindDependencies)
24+
include(IFEMLTO)
2425
include(IFEMAddTargets)
2526
include(IFEMOptionsDownstream)
2627
include("${CMAKE_CURRENT_LIST_DIR}/IFEMTargets.cmake")

0 commit comments

Comments
 (0)