lld runs LTO even if -fno-lto is passed
Asked Answered
H

1

8

I have a CMake project with several subprojects that create static libraries built with -flto=thin.

The project has a lot of tests that are linked against the aforementioned libraries. With LTO it takes a lot of time to build tests, therefore I have disabled LTO for tests using -fno-lto.

What I noticed though, is that lld performs LTO on tests even with -fno-lto. If I run the linker with --time-trace I can see that the majority of the time is spent on LTO.

My questions are:

  1. Is this expected? If so I can assume that lld performs LTO whenever it finds the LTO info in the object it links.
  2. If not, is there a way to disable this behavior? Adding -fno-lto to the compiler does not seem to work, and lld does not have a param to explicitly disable LTO.
  3. If not, is this a bug?

Update 1:

This is how I handle lto in CMake:

# Enable Thin LTO only on non-test targets.
if(ENABLE_LTO)
  if (IS_TEST)
    target_compile_options(${TARGET} PRIVATE -fno-lto)
    # Probably pointless.
    target_link_options(${TARGET} PRIVATE -fno-lto)
  else()
    message(STATUS "ENABLE_LTO on target ${TARGET})")
    target_compile_options(${TARGET} PRIVATE -flto=thin)
    target_link_options(${TARGET} PRIVATE -flto=thin -Wl,--thinlto-cache-dir=${CMAKE_BINARY_DIR}/lto.cache)
  endif()
endif()
Hepzi answered 10/5, 2022 at 17:2 Comment(3)
Have you specified -fno-lto after -flto=thin (the rightmost settings wins)? Have you specified -fno-lto in a compiler flags (it should not be set on the linker flags)?Uteutensil
The tests do not have the -flto=thin at all (hence -fno-lto should be the default). To be sure I have explicitly added the -fno-lto param to the compiler. Updating the question.Hepzi
I cross-posted this in the LLVM bug tracker:github.com/llvm/llvm-project/issues/55431Hepzi
C
6

If you compile the libraries with -flto then, at least for gcc, the object files will only contain the intermediate language and no binary code.

That means when you link them into your test cases compiled with -fno-lto there is no binary code to link to. The linker has no choice but to first compile the intermediate language into binary for each needed function, which you would see as an LTO phase.

In gcc there is an option -ffat-lto-objects that tells gcc to include both the intermediate language as well as binary code in the object files. They can then be used for linking with LTO or without. The drawback is that this takes a bit longer to compile and produces larger object files.

You have to check if clang has the same option, they are usually pretty compatible with options.

Caplan answered 15/5, 2022 at 15:48 Comment(2)
Thanks for the answer, this could explain the behavior. Unfortunately, clang does not seem to support -ffat-lto-objects.Hepzi
I posted this question to see if it is possible to have "fat LTO objects" with clang: #72260820Hepzi

© 2022 - 2024 — McMap. All rights reserved.