diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 176fb72dfdc5e..7b2cc58ce42c9 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -367,7 +367,12 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( (InlineAttr::None, _) if instance.def.requires_inline(cx.tcx) => InlineAttr::Hint, (inline, _) => inline, }; - to_add.extend(inline_attr(cx, inline)); + if cx.tcx.has_inline_always_override(instance) { + eprintln!("Applying override"); + to_add.extend(inline_attr(cx, InlineAttr::Always)); + } else { + to_add.extend(inline_attr(cx, inline)); + } // The `uwtable` attribute according to LLVM is: // diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 7243f87ee6380..6ef5cb1ab5fad 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -209,6 +209,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 0759fa3da428a..a3b2850a334a7 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -78,8 +78,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, }; @@ -3395,6 +3395,14 @@ impl<'tcx> TyCtxt<'tcx> { pub fn do_not_recommend_impl(self, def_id: DefId) -> bool { 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)) + } } /// Parameter attributes that can only be determined by examining the body of a function instead diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 5b4068740a159..3e917b680203e 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2249,6 +2249,9 @@ options! { - hashes of green query instances - hash collisions of query keys - hash collisions when creating dep-nodes"), + 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],