From 198fc5dd20e4260c39eecd358fa9e5da7be19312 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 15 May 2025 21:27:02 +0000 Subject: [PATCH] Hack together inline-always-overrides --- compiler/rustc_codegen_llvm/src/attributes.rs | 5 +++++ compiler/rustc_middle/src/mir/mono.rs | 2 ++ compiler/rustc_middle/src/ty/context.rs | 12 ++++++++++-- compiler/rustc_session/src/options.rs | 3 +++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 8070ea0b3e927..2e4eaacb4f54d 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -35,6 +35,11 @@ pub(crate) fn inline_attr<'ll, 'tcx>( tcx: TyCtxt<'tcx>, instance: ty::Instance<'tcx>, ) -> Option<&'ll Attribute> { + if tcx.has_inline_always_override(instance) { + eprintln!("Applying override"); + return Some(AttributeKind::AlwaysInline.create_attr(cx.llcx)); + } + // `optnone` requires `noinline` let codegen_fn_attrs = tcx.codegen_fn_attrs(instance.def_id()); let inline = match (codegen_fn_attrs.inline, &codegen_fn_attrs.optimize) { diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 6b45b2dc3ff50..feab672c8b834 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -206,6 +206,8 @@ impl<'tcx> MonoItem<'tcx> { if codegen_fn_attrs.inline.always() { return InstantiationMode::LocalCopy; } + // FIXME: Ideally we'd check has_inline_always_override here, but we can't because symbol names + // depend on instantiation mode so instantiation mode can't depend on symbol name. // #[inline(never)] functions in general are poor candidates for inlining and thus since // LocalCopy generally increases code size for the benefit of optimizations from inlining, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 3c5c21a7a89c2..1110e80f88d8c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -80,8 +80,8 @@ use crate::traits::solve::{ use crate::ty::predicate::ExistentialPredicateStableCmpExt as _; use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, GenericArg, GenericArgs, - GenericArgsRef, GenericParamDefKind, List, ListWithCachedTypeInfo, ParamConst, ParamTy, - Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, + GenericArgsRef, GenericParamDefKind, Instance, List, ListWithCachedTypeInfo, ParamConst, + ParamTy, Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, ValTree, ValTreeKind, Visibility, }; @@ -3552,6 +3552,14 @@ impl<'tcx> TyCtxt<'tcx> { self.get_diagnostic_attr(def_id, sym::do_not_recommend).is_some() } + pub fn has_inline_always_override(self, instance: Instance<'tcx>) -> bool { + let Some(overrides) = &self.sess.opts.unstable_opts.inline_always_overrides else { + return false; + }; + let symbol_name = self.symbol_name(instance).name; + overrides.iter().any(|o| symbol_name.starts_with(o)) + } + /// Whether this def is one of the special bin crate entrypoint functions that must have a /// monomorphization and also not be internalized in the bin crate. pub fn is_entrypoint(self, def_id: DefId) -> bool { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 6dd90546de1b0..d88738729d941 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2368,6 +2368,9 @@ options! { - hash collisions when creating dep-nodes"), indirect_branch_cs_prefix: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER], "add `cs` prefix to `call` and `jmp` to indirect thunks (default: no)"), + inline_always_overrides: Option> = (None, parse_opt_comma_list, [TRACKED], + "comma-separated list of full paths to functions to treat as if they are inline(always)" + ), inline_llvm: bool = (true, parse_bool, [TRACKED], "enable LLVM inlining (default: yes)"), inline_mir: Option = (None, parse_opt_bool, [TRACKED],