From 73c60aec3469d12690f4976d05bca42b2b8b42db Mon Sep 17 00:00:00 2001 From: purahan Date: Thu, 9 Apr 2026 23:53:16 +0530 Subject: [PATCH] Fix Enzyme autodiff ICE by anchoring metadata markers in core Fixes a crash where Enzyme fails to compute derivatives when compiling with LTO. Previously, global metadata markers (like `enzyme_dup`) were declared in the LLVM backend (`rustc_codegen_llvm`). However, LLVM's Link-Time Optimization aggressively stripped their initializers, causing Enzyme to misinterpret them as active external variables rather than constant structural markers. This fix resolves the issue by defining these structural anchors directly within the `core` library as `#[no_mangle]` statics. By anchoring them in the standard library, they are natively protected from LTO stripping, ensuring Enzyme correctly parses them as constant metadata during derivative generation. --- library/core/src/lib.rs | 50 +++++++++++++++++++++ tests/run-make/symbols-all-mangled/rmake.rs | 4 ++ 2 files changed, 54 insertions(+) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 35f93d8fb33b2..52813826d5f3b 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -385,3 +385,53 @@ pub mod simd { } include!("primitive_docs.rs"); + +// Global metadata markers for the Enzyme autodiff backend. +// These are not read or written to by Rust code. They are required to survive +// Link-Time Optimization (LTO) so that Enzyme can correctly identify them +// as constant metadata variables when computing derivatives. +#[unstable(feature = "autodiff", issue = "124509")] +#[allow(non_upper_case_globals)] +#[allow(missing_docs)] +#[doc(hidden)] +pub mod enzyme_globals { + #[unsafe(no_mangle)] + #[unstable(feature = "autodiff", issue = "124509")] + #[doc(hidden)] + pub static enzyme_const: u8 = 0; + + #[unsafe(no_mangle)] + #[unstable(feature = "autodiff", issue = "124509")] + #[doc(hidden)] + pub static enzyme_out: u8 = 0; + + #[unsafe(no_mangle)] + #[unstable(feature = "autodiff", issue = "124509")] + #[doc(hidden)] + pub static enzyme_dup: u8 = 0; + + #[unsafe(no_mangle)] + #[unstable(feature = "autodiff", issue = "124509")] + #[doc(hidden)] + pub static enzyme_dupv: u8 = 0; + + #[unsafe(no_mangle)] + #[unstable(feature = "autodiff", issue = "124509")] + #[doc(hidden)] + pub static enzyme_dupnoneed: u8 = 0; + + #[unsafe(no_mangle)] + #[unstable(feature = "autodiff", issue = "124509")] + #[doc(hidden)] + pub static enzyme_dupnoneedv: u8 = 0; + + #[unsafe(no_mangle)] + #[unstable(feature = "autodiff", issue = "124509")] + #[doc(hidden)] + pub static enzyme_primal_return: u8 = 0; + + #[unsafe(no_mangle)] + #[unstable(feature = "autodiff", issue = "124509")] + #[doc(hidden)] + pub static enzyme_width: u8 = 0; +} diff --git a/tests/run-make/symbols-all-mangled/rmake.rs b/tests/run-make/symbols-all-mangled/rmake.rs index 2cf579758002a..ec5924531f9f6 100644 --- a/tests/run-make/symbols-all-mangled/rmake.rs +++ b/tests/run-make/symbols-all-mangled/rmake.rs @@ -39,6 +39,10 @@ fn symbols_check_archive(path: &str) { continue; // Unfortunately LLVM doesn't allow us to mangle this symbol } + if name.starts_with("enzyme_") { + continue; // Enzyme metadata markers are allowed to be unmangled + } + if name.contains(".llvm.") { // Starting in LLVM 21 we get various implementation-detail functions which // contain .llvm. that are not a problem.