-
-
Notifications
You must be signed in to change notification settings - Fork 16.4k
-Cpasses transformations are missing from embedded bitcode with one codegen unit #159533
Copy link
Copy link
Open
Open
Copy link
Labels
A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-bugCategory: This is a bug.Category: This is a bug.E-needs-investigationCall for participation: This issues needs some investigation to determine current statusCall for participation: This issues needs some investigation to determine current statusP-mediumMedium priorityMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.Performance or correctness regression from one stable version to another.
Description
Activity
Metadata
Metadata
Assignees
Labels
A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-bugCategory: This is a bug.Category: This is a bug.E-needs-investigationCall for participation: This issues needs some investigation to determine current statusCall for participation: This issues needs some investigation to determine current statusP-mediumMedium priorityMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.Performance or correctness regression from one stable version to another.
Summary
When an rlib is compiled with
-Cembed-bitcode=yesand a custom LLVM pass, the emitted object code reflects the pass but the embedded bitcode may not.With
-Ccodegen-units=1, the embedded bitcode is serialized before-Cpassesruns. With multiple codegen units, it is serialized after the pass.As a result, a transformation requested through
-Cpassescan silently disappear when another crate consumes the rlib through LTO.Code
Compile the same crate with one and two codegen units:
After extracting each rlib's object member, the embedded bitcode can be read with LLVM tools:
On Mach-O, the section name is
__LLVM,__bitcodeinstead of.llvmbc:The result is:
The machine-code object is lowered in both cases. On AArch64, both objects contain the same non-atomic sequence:
The inconsistency is between the object code and the bitcode stored alongside it.
Expected behavior
The effect of a pre-link custom pass should be represented consistently in embedded LTO bitcode and should not depend on the number of codegen units.
In particular, because
-Cpassesis intentionally not rerun during final LTO, its pre-link transformations need to be present in the bitcode supplied to LTO.Regression
This worked with Rust 1.86.0: the one-CGU embedded bitcode contained no atomic operations.
It regressed in Rust 1.87.0. Rust 1.88.0 and later retain the
atomicrmwin the one-CGU embedded bitcode.The regression appears related to #133250, which moved embedded-bitcode serialization into the pre-link optimization pipeline.
In the
PreLinkNoLTOpath,ThinLTOBitcodeWriterPassis scheduled beforeExtraPasses. In the pre-link ThinLTO path, the bitcode writer is scheduled afterExtraPasses. This appears to explain the codegen-unit-dependent result.The final LTO stage does not repair the difference because #97969 intentionally made
-Cpassespre-link-only.Version
Reproduced on the latest nightly available on 2026-07-18:
@rustbot modify labels: +regression-from-stable-to-stable -regression-untriaged
cc @dianqk, since this appears related to the embedded-bitcode pipeline added in #133250.