Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix linker-plugin-lto only doing thin lto #136840

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Flakebi
Copy link
Contributor

@Flakebi Flakebi commented Feb 10, 2025

When rust provides LLVM bitcode files to lld and the bitcode contains
function summaries as used for thin lto, lld defaults to using thin lto.
This prevents some optimizations that are only applied for fat lto.

Set the ThinLTO=0 module flag to signal lld to do fat lto.

The analogous code in clang that sets this flag is here:
https://github.com/llvm/llvm-project/blob/560149b5e3c891c64899e9912e29467a69dc3a4c/clang/lib/CodeGen/BackendUtil.cpp#L1150

The code in LLVM that queries the flag and defaults to thin lto if not
set is here:
https://github.com/llvm/llvm-project/blob/e258bca9505f35e0a22cb213a305eea9b76d11ea/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp#L4441-L4446

r? @workingjubilee, as you’ve been reviewing most other amdgpu patches, not sure if there should be other reviewers for lto.

@rustbot
Copy link
Collaborator

rustbot commented Feb 10, 2025

Could not assign reviewer from: workingjubilee.
User(s) workingjubilee are either the PR author, already assigned, or on vacation. Please use r? to specify someone else to assign.

@rustbot
Copy link
Collaborator

rustbot commented Feb 10, 2025

r? @jieyouxu

rustbot has assigned @jieyouxu.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added A-run-make Area: port run-make Makefiles to rmake.rs S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Feb 10, 2025
@rustbot
Copy link
Collaborator

rustbot commented Feb 10, 2025

This PR modifies tests/run-make/. If this PR is trying to port a Makefile
run-make test to use rmake.rs, please update the
run-make port tracking issue
so we can track our progress. You can either modify the tracking issue
directly, or you can comment on the tracking issue and link this PR.

cc @jieyouxu

@Flakebi Flakebi mentioned this pull request Feb 10, 2025
16 tasks
@workingjubilee
Copy link
Member

I have barely any idea about LTO besides "it happens and it involves dlopening a compiler and shoving its serialized data back in it" tbh soo

@jieyouxu
Copy link
Member

Unfortunately I have no clue either, so

r? compiler

@rustbot rustbot assigned fee1-dead and unassigned jieyouxu Feb 11, 2025
@Flakebi
Copy link
Contributor Author

Flakebi commented Feb 11, 2025

For reference, the code that switches to thin lto when the flag is not set is here: https://github.com/llvm/llvm-project/blob/e258bca9505f35e0a22cb213a305eea9b76d11ea/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp#L4441-L4446

  // By default we compile with ThinLTO if the module has a summary, but the
  // client can request full LTO with a module flag.
  bool IsThinLTO = true;
  if (auto *MD =
          mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("ThinLTO")))
    IsThinLTO = MD->getZExtValue();

The code in clang that sets the flag, which is replicated here for Rust is here: https://github.com/llvm/llvm-project/blob/560149b5e3c891c64899e9912e29467a69dc3a4c/clang/lib/CodeGen/BackendUtil.cpp#L1150

        if (!TheModule->getModuleFlag("ThinLTO") && !CodeGenOpts.UnifiedLTO)
          TheModule->addModuleFlag(llvm::Module::Error, "ThinLTO", uint32_t(0));

// Disable ThinLTO if fat lto is requested. Otherwise lld defaults to thin lto.
if sess.lto() == config::Lto::Fat {
llvm::add_module_flag_u32(llmod, llvm::ModuleFlagMergeBehavior::Override, "ThinLTO", 0);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if a dependency is built with lto=true (aka lto=fat), but then the user wants to use thinLTO? I'm pretty sure the standard library is built with lto=true for example, but that shouldn't prevent thinLTO from ever working.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question, it seems to change somewhat, but still work in general. I added a test for this.
What changes: Without this change, the test passes when
lib is compiled with O0 and main with O3 and

  1. lib uses lto=thin and main uses lto=thin
  2. lib uses lto=thin and main uses lto=fat
  3. lib uses lto=fat and main uses lto=thin
  4. lib uses lto=fat and main uses lto=fat

With this change, all of these keep passing except for case 3 (lib uses lto=fat and main uses lto=thin).
When lib is compiled with O1, O2 or O3, case 3 passes as well.
I assume this is the important case, as the standard library is compiled with optimizations.
(And lto with O0 is kinda questionable, except maybe for nvptx and amdgpu, but they require lto=fat anyway.)

@rust-log-analyzer

This comment has been minimized.

@fee1-dead
Copy link
Member

r? compiler

@rustbot rustbot assigned SparrowLii and unassigned fee1-dead Feb 16, 2025
Copy link
Member

@SparrowLii SparrowLii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know little about lto, either. I think it would be much more acceptable if this PR could limit the change to amdhsa conditions.

r? compiler

@@ -290,6 +290,11 @@ pub(crate) unsafe fn create_module<'ll>(
);
}

// Disable ThinLTO if fat lto is requested. Otherwise lld defaults to thin lto.
Copy link
Member

@SparrowLii SparrowLii Feb 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds counterintuitive. Can you explain the relationship between the user's lto option and llvm's lto in the comments?

And I think it needs a individual test to ensure that the previous lto=fat option is not affected

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the comment, is it clearer now?

(I want to affect the current lto=fat option, as it currently does thin lto, which I think is not intended and a bug :))

@rustbot rustbot assigned Nadrieril and BoxyUwU and unassigned SparrowLii Feb 17, 2025
@Kobzol
Copy link
Contributor

Kobzol commented Feb 17, 2025

@DianQK Does this interact with your recent patch?

@DianQK
Copy link
Member

DianQK commented Feb 17, 2025

@DianQK Does this interact with your recent patch?

IMO, they aren't directly related.

@Nadrieril
Copy link
Member

r? codegen

@rustbot rustbot assigned saethlin and unassigned Nadrieril and BoxyUwU Feb 17, 2025
@Flakebi
Copy link
Contributor Author

Flakebi commented Feb 18, 2025

I think it would be much more acceptable if this PR could limit the change to amdhsa conditions.

AFAIU, fat LTO + linker-plugin-lto is currently broken for all targets, as lld just does thin lto, even if the user requested fat lto. Setting the ThinLTO=0 metadata fixes that and gets lld to do actual fat lto.

It’s just that x86 and other targets run fine with only thin lto. GPU targets (e.g. amdgpu and nvptx) currently require lto to function correctly. This may change when hardware vendors focus more on linking, but I think the performance dip makes it rather unattractive today. So, if fat LTO is not working correctly, it becomes apparent quickly on GPU targets, not so on x86.

I can move the amdhsa part to a separate PR if that’s preferred. The reason I included it here, is that I only managed to write a test for amdgpu so far and I wanted to include a test.

@Flakebi Flakebi force-pushed the linker-plugin-lto-fat branch from 0d63f96 to 2d33f69 Compare February 19, 2025 23:57
@rustbot
Copy link
Collaborator

rustbot commented Feb 19, 2025

The run-make-support library was changed

cc @jieyouxu

@Flakebi
Copy link
Contributor Author

Flakebi commented Feb 19, 2025

I found a way to reproduce the same on x86 by creating an object file that does not contain function summaries. I added a test and removed all the amdhsa-specific code from this PR. Diff to last push

@rust-log-analyzer

This comment has been minimized.

@Flakebi Flakebi force-pushed the linker-plugin-lto-fat branch from 2d33f69 to d421833 Compare February 20, 2025 09:27
When rust provides LLVM bitcode files to lld and the bitcode contains
function summaries as used for thin lto, lld defaults to using thin lto.
This prevents some optimizations that are only applied for fat lto.

Set the `ThinLTO=0` module flag to signal lld to do fat lto.

The analogous code in clang that sets this flag is here:
https://github.com/llvm/llvm-project/blob/560149b5e3c891c64899e9912e29467a69dc3a4c/clang/lib/CodeGen/BackendUtil.cpp#L1150

The code in LLVM that queries the flag and defaults to thin lto if not
set is here:
https://github.com/llvm/llvm-project/blob/e258bca9505f35e0a22cb213a305eea9b76d11ea/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp#L4441-L4446
@Flakebi Flakebi force-pushed the linker-plugin-lto-fat branch from d421833 to b692fa0 Compare February 20, 2025 09:27
@Flakebi
Copy link
Contributor Author

Flakebi commented Feb 20, 2025

Try to fix the test by forcing rust-lld (diff)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-run-make Area: port run-make Makefiles to rmake.rs S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.