From a240e48192b0744c1039e7573bb206580d9000b0 Mon Sep 17 00:00:00 2001 From: wilbertbw Date: Thu, 27 Nov 2025 00:44:14 -0500 Subject: [PATCH 1/5] simplified autodiff handling, replaced Instance with function pointer --- .../rustc_codegen_llvm/src/builder/autodiff.rs | 16 +++++++--------- compiler/rustc_codegen_llvm/src/intrinsic.rs | 6 +++++- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs index 4b433e2b63616..ec3aff39e248e 100644 --- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs +++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs @@ -4,7 +4,7 @@ use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode}; use rustc_ast::expand::typetree::FncTree; use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods}; -use rustc_middle::ty::{Instance, PseudoCanonicalInput, TyCtxt, TypingEnv}; +use rustc_middle::ty::{PseudoCanonicalInput, Ty, TyCtxt, TypingEnv}; use rustc_middle::{bug, ty}; use rustc_target::callconv::PassMode; use tracing::debug; @@ -16,25 +16,23 @@ use crate::llvm::{self, TRUE, Type, Value}; pub(crate) fn adjust_activity_to_abi<'tcx>( tcx: TyCtxt<'tcx>, - instance: Instance<'tcx>, + fn_ptr_ty: Ty<'tcx>, typing_env: TypingEnv<'tcx>, da: &mut Vec, ) { - let fn_ty = instance.ty(tcx, typing_env); - - if !matches!(fn_ty.kind(), ty::FnDef(..)) { - bug!("expected fn def for autodiff, got {:?}", fn_ty); + if !matches!(fn_ptr_ty.kind(), ty::FnPtr(_)) { + bug!("expected fn ptr for autodiff, got {:?}", fn_ptr_ty); } // We don't actually pass the types back into the type system. // All we do is decide how to handle the arguments. - let sig = fn_ty.fn_sig(tcx).skip_binder(); + let sig = fn_ptr_ty.fn_sig(tcx).skip_binder(); // FIXME(Sa4dUs): pass proper varargs once we have support for differentiating variadic functions let Ok(fn_abi) = - tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty()))) + tcx.fn_abi_of_fn_ptr(fn_ptr_ty, ty::List::empty()); else { - bug!("failed to get fn_abi of instance with empty varargs"); + bug!("failed to get fn_abi of fn_ptr with empty varargs"); }; let mut new_activities = vec![]; diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index b4057eea735ea..198b8ab351b77 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1329,9 +1329,13 @@ fn codegen_autodiff<'ll, 'tcx>( bug!("could not find autodiff attrs") }; + let fn_ty = fn_source.ty(tcx, TypingEnv::fully_monomorphized()); + let fn_sig = fn_ty.fn_sig(tcx); + let fn_ptr_ty = tcx.mk_fn_ptr(fn_sig); + adjust_activity_to_abi( tcx, - fn_source, + fn_ptr_ty, TypingEnv::fully_monomorphized(), &mut diff_attrs.input_activity, ); From f7684f9872f8715f0c2b1b73085dfb976c2d481a Mon Sep 17 00:00:00 2001 From: wilbertbw Date: Thu, 27 Nov 2025 01:15:12 -0500 Subject: [PATCH 2/5] fixed syntax with fn_ab_of_fn_ptr call --- compiler/rustc_codegen_llvm/src/builder/autodiff.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs index ec3aff39e248e..5a8c034586161 100644 --- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs +++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs @@ -29,9 +29,7 @@ pub(crate) fn adjust_activity_to_abi<'tcx>( let sig = fn_ptr_ty.fn_sig(tcx).skip_binder(); // FIXME(Sa4dUs): pass proper varargs once we have support for differentiating variadic functions - let Ok(fn_abi) = - tcx.fn_abi_of_fn_ptr(fn_ptr_ty, ty::List::empty()); - else { + let Ok(fn_abi) = tcx.fn_abi_of_fn_ptr(fn_ptr_ty, ty::List::empty()) else { bug!("failed to get fn_abi of fn_ptr with empty varargs"); }; From ff9d1cfe3173a9a14778e3e544caf53dc8b305d9 Mon Sep 17 00:00:00 2001 From: wilbertbw Date: Thu, 27 Nov 2025 01:36:41 -0500 Subject: [PATCH 3/5] fixed errors with arguments in autodiff.rs and function pointer creation in /compiler/rustc_codegen_llvm/src/intrinsic.rs --- compiler/rustc_codegen_llvm/src/builder/autodiff.rs | 5 +++-- compiler/rustc_codegen_llvm/src/intrinsic.rs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs index 5a8c034586161..c50936a31d908 100644 --- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs +++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs @@ -20,7 +20,7 @@ pub(crate) fn adjust_activity_to_abi<'tcx>( typing_env: TypingEnv<'tcx>, da: &mut Vec, ) { - if !matches!(fn_ptr_ty.kind(), ty::FnPtr(_)) { + if !matches!(fn_ptr_ty.kind(), ty::FnPtr(..)) { bug!("expected fn ptr for autodiff, got {:?}", fn_ptr_ty); } @@ -29,7 +29,8 @@ pub(crate) fn adjust_activity_to_abi<'tcx>( let sig = fn_ptr_ty.fn_sig(tcx).skip_binder(); // FIXME(Sa4dUs): pass proper varargs once we have support for differentiating variadic functions - let Ok(fn_abi) = tcx.fn_abi_of_fn_ptr(fn_ptr_ty, ty::List::empty()) else { + let pci = PseudoCanonicalInput { typing_env, value: (sig, ty::List::empty()) }; + let Ok(fn_abi) = tcx.fn_abi_of_fn_ptr(pci) else { bug!("failed to get fn_abi of fn_ptr with empty varargs"); }; diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 198b8ab351b77..011ea57955112 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1331,7 +1331,7 @@ fn codegen_autodiff<'ll, 'tcx>( let fn_ty = fn_source.ty(tcx, TypingEnv::fully_monomorphized()); let fn_sig = fn_ty.fn_sig(tcx); - let fn_ptr_ty = tcx.mk_fn_ptr(fn_sig); + let fn_ptr_ty = Ty::new_fn_ptr(tcx, fn_sig); adjust_activity_to_abi( tcx, From 41703e08be5b2a81fb0646ccb2f90a5338324bd4 Mon Sep 17 00:00:00 2001 From: wilbertbw Date: Thu, 27 Nov 2025 02:09:38 -0500 Subject: [PATCH 4/5] updated pci argument for fn_abi_of_fn_ptr call, sig does not skip_binder --- compiler/rustc_codegen_llvm/src/builder/autodiff.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs index c50936a31d908..00d0fbb626829 100644 --- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs +++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs @@ -26,10 +26,11 @@ pub(crate) fn adjust_activity_to_abi<'tcx>( // We don't actually pass the types back into the type system. // All we do is decide how to handle the arguments. - let sig = fn_ptr_ty.fn_sig(tcx).skip_binder(); + let poly_sig = fn_ptr_ty.fn_sig(tcx); + let sig = poly_sig.skip_binder(); // FIXME(Sa4dUs): pass proper varargs once we have support for differentiating variadic functions - let pci = PseudoCanonicalInput { typing_env, value: (sig, ty::List::empty()) }; + let pci = PseudoCanonicalInput { typing_env, value: (poly_sig, ty::List::empty()) }; let Ok(fn_abi) = tcx.fn_abi_of_fn_ptr(pci) else { bug!("failed to get fn_abi of fn_ptr with empty varargs"); }; From da0ad993244c41cc10eef38f65644ed1b6b9b773 Mon Sep 17 00:00:00 2001 From: wilbertbw Date: Thu, 1 Jan 2026 14:49:55 -0500 Subject: [PATCH 5/5] implemented changes from FIXMEs from Issue 149164 --- .../src/cross_crate_inline.rs | 8 --- compiler/rustc_monomorphize/src/collector.rs | 5 -- .../src/collector/autodiff.rs | 50 ------------------- 3 files changed, 63 deletions(-) delete mode 100644 compiler/rustc_monomorphize/src/collector/autodiff.rs diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 71bdafa958ca1..84c1d13e63714 100644 --- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -35,14 +35,6 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { return true; } - // FIXME(autodiff): replace this as per discussion in https://github.com/rust-lang/rust/pull/149033#discussion_r2535465880 - if tcx.has_attr(def_id, sym::autodiff_forward) - || tcx.has_attr(def_id, sym::autodiff_reverse) - || tcx.has_attr(def_id, sym::rustc_autodiff) - { - return true; - } - if tcx.has_attr(def_id, sym::rustc_intrinsic) { // Intrinsic fallback bodies are always cross-crate inlineable. // To ensure that the MIR inliner doesn't cluelessly try to inline fallback diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 4b2f8e03afc13..c6becae315c9d 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -205,8 +205,6 @@ //! this is not implemented however: a mono item will be produced //! regardless of whether it is actually needed or not. -mod autodiff; - use std::cell::OnceCell; use std::ops::ControlFlow; @@ -240,7 +238,6 @@ use rustc_span::source_map::{Spanned, dummy_spanned, respan}; use rustc_span::{DUMMY_SP, Span}; use tracing::{debug, instrument, trace}; -use crate::collector::autodiff::collect_autodiff_fn; use crate::errors::{ self, EncounteredErrorWhileInstantiating, EncounteredErrorWhileInstantiatingGlobalAsm, NoOptimizedMir, RecursionLimit, @@ -989,8 +986,6 @@ fn visit_instance_use<'tcx>( return; } if let Some(intrinsic) = tcx.intrinsic(instance.def_id()) { - collect_autodiff_fn(tcx, instance, intrinsic, output); - if let Some(_requirement) = ValidityRequirement::from_intrinsic(intrinsic.name) { // The intrinsics assert_inhabited, assert_zero_valid, and assert_mem_uninitialized_valid will // be lowered in codegen to nothing or a call to panic_nounwind. So if we encounter any diff --git a/compiler/rustc_monomorphize/src/collector/autodiff.rs b/compiler/rustc_monomorphize/src/collector/autodiff.rs deleted file mode 100644 index e3646596e75e6..0000000000000 --- a/compiler/rustc_monomorphize/src/collector/autodiff.rs +++ /dev/null @@ -1,50 +0,0 @@ -use rustc_middle::bug; -use rustc_middle::ty::{self, GenericArg, IntrinsicDef, TyCtxt}; - -use crate::collector::{MonoItems, create_fn_mono_item}; - -// Here, we force both primal and diff function to be collected in -// mono so this does not interfere in `autodiff` intrinsics -// codegen process. If they are unused, LLVM will remove them when -// compiling with O3. -// FIXME(autodiff): Remove this whole file, as per discussion in -// https://github.com/rust-lang/rust/pull/149033#discussion_r2535465880 -pub(crate) fn collect_autodiff_fn<'tcx>( - tcx: TyCtxt<'tcx>, - instance: ty::Instance<'tcx>, - intrinsic: IntrinsicDef, - output: &mut MonoItems<'tcx>, -) { - if intrinsic.name != rustc_span::sym::autodiff { - return; - }; - - collect_autodiff_fn_from_arg(instance.args[0], tcx, output); -} - -fn collect_autodiff_fn_from_arg<'tcx>( - arg: GenericArg<'tcx>, - tcx: TyCtxt<'tcx>, - output: &mut MonoItems<'tcx>, -) { - let (instance, span) = match arg.kind() { - ty::GenericArgKind::Type(ty) => match ty.kind() { - ty::FnDef(def_id, substs) => { - let span = tcx.def_span(def_id); - let instance = ty::Instance::expect_resolve( - tcx, - ty::TypingEnv::non_body_analysis(tcx, def_id), - *def_id, - substs, - span, - ); - - (instance, span) - } - _ => bug!("expected autodiff function"), - }, - _ => bug!("expected type when matching autodiff arg"), - }; - - output.push(create_fn_mono_item(tcx, instance, span)); -}