Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4e11683

Browse files
committed
Add #[rustc_early_inline]
1 parent f34ba77 commit 4e11683

File tree

13 files changed

+87
-42
lines changed

13 files changed

+87
-42
lines changed

‎compiler/rustc_attr_parsing/src/attributes/inline.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,16 @@ impl<S: Stage> SingleAttributeParser<S> for RustcForceInlineParser {
9393
))
9494
}
9595
}
96+
97+
pub(crate) struct RustcEarlyInlineParser;
98+
99+
impl<S: Stage> SingleAttributeParser<S> for RustcEarlyInlineParser {
100+
const PATH: &'static [Symbol] = &[sym::rustc_early_inline];
101+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
102+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
103+
const TEMPLATE: AttributeTemplate = template!(Word);
104+
105+
fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> {
106+
Some(AttributeKind::Inline(InlineAttr::Early, cx.attr_span))
107+
}
108+
}

‎compiler/rustc_attr_parsing/src/context.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use crate::attributes::codegen_attrs::{
2424
use crate::attributes::confusables::ConfusablesParser;
2525
use crate::attributes::deprecation::DeprecationParser;
2626
use crate::attributes::dummy::DummyParser;
27-
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
27+
use crate::attributes::inline::{InlineParser, RustcEarlyInlineParser,RustcForceInlineParser};
2828
use crate::attributes::link_attrs::{
2929
ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser,
3030
LinkSectionParser, StdInternalSymbolParser,
@@ -170,6 +170,7 @@ attribute_parsers!(
170170
Single<PathAttributeParser>,
171171
Single<ProcMacroDeriveParser>,
172172
Single<RustcBuiltinMacroParser>,
173+
Single<RustcEarlyInlineParser>,
173174
Single<RustcForceInlineParser>,
174175
Single<RustcLayoutScalarValidRangeEnd>,
175176
Single<RustcLayoutScalarValidRangeStart>,

‎compiler/rustc_codegen_gcc/src/attributes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ fn inline_attr<'gcc, 'tcx>(
6767
Some(FnAttribute::AlwaysInline)
6868
}
6969
}
70-
InlineAttr::Hint => Some(FnAttribute::Inline),
70+
InlineAttr::Hint | InlineAttr::Early=> Some(FnAttribute::Inline),
7171
InlineAttr::Force { .. } => Some(FnAttribute::AlwaysInline),
7272
InlineAttr::Never => {
7373
if cx.sess().target.arch != "amdgpu" {

‎compiler/rustc_codegen_llvm/src/attributes.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ fn inline_attr<'ll>(cx: &CodegenCx<'ll, '_>, inline: InlineAttr) -> Option<&'ll
5252
return Some(AttributeKind::NoInline.create_attr(cx.llcx));
5353
}
5454
match inline {
55-
InlineAttr::Hint => Some(AttributeKind::InlineHint.create_attr(cx.llcx)),
55+
InlineAttr::Hint | InlineAttr::Early => {
56+
Some(AttributeKind::InlineHint.create_attr(cx.llcx))
57+
}
5658
InlineAttr::Always | InlineAttr::Force { .. } => {
5759
Some(AttributeKind::AlwaysInline.create_attr(cx.llcx))
5860
}

‎compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ fn check_result(
473473

474474
// warn that inline has no effect when no_sanitize is present
475475
if !codegen_fn_attrs.no_sanitize.is_empty()
476-
&& codegen_fn_attrs.inline.always()
476+
&& codegen_fn_attrs.inline.always_in_codegen()
477477
&& let (Some(no_sanitize_span), Some(inline_span)) =
478478
(interesting_spans.no_sanitize, interesting_spans.inline)
479479
{

‎compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,11 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
11231123
rustc_no_mir_inline, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes,
11241124
"`#[rustc_no_mir_inline]` prevents the MIR inliner from inlining a function while not affecting codegen"
11251125
),
1126+
rustc_attr!(
1127+
rustc_early_inline, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes,
1128+
"`#[rustc_early_inline]` inlines non-generic calls to trivial methods even in debug, \
1129+
while still allowing them to be codegen'd for generic calls"
1130+
),
11261131
rustc_attr!(
11271132
rustc_force_inline, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, EncodeCrossCrate::Yes,
11281133
"`#[rustc_force_inline]` forces a free function to be inlined"

‎compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,20 @@ pub enum InlineAttr {
2424
attr_span: Span,
2525
reason: Option<Symbol>,
2626
},
27+
/// `#[rustc_early_inline]` will always inline calls to a known impl in MIR.
28+
///
29+
/// You can think of this as either
30+
/// - Force, but without the "do not codegen as a function ever" restriction.
31+
/// - Always, but only for MIR.
32+
Early,
2733
}
2834

2935
impl InlineAttr {
30-
pub fn always(&self) -> bool {
36+
pub fn always_in_codegen(&self) -> bool {
3137
match self {
32-
InlineAttr::Always | InlineAttr::Force { .. } => true,
33-
InlineAttr::None | InlineAttr::Hint | InlineAttr::Never => false,
38+
InlineAttr::Always => true,
39+
InlineAttr::None | InlineAttr::Hint | InlineAttr::Early | InlineAttr::Never => false,
40+
InlineAttr::Force { .. } => panic!("Shouldn't be codegen'ing {self:?}"),
3441
}
3542
}
3643
}
@@ -342,7 +349,7 @@ pub enum AttributeKind {
342349
reason: Option<Symbol>,
343350
},
344351

345-
/// Represents `#[inline]` and `#[rustc_force_inline]`.
352+
/// Represents `#[inline]` and `#[rustc_force_inline]` and `#[rustc_early_inline]`.
346353
Inline(InlineAttr, Span),
347354

348355
/// Represents `#[link_name]`.

‎compiler/rustc_middle/src/mir/mono.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ impl<'tcx> MonoItem<'tcx> {
205205

206206
// To ensure that #[inline(always)] can be inlined as much as possible, especially in unoptimized
207207
// builds, we always select LocalCopy.
208-
if codegen_fn_attrs.inline.always() {
208+
if codegen_fn_attrs.inline.always_in_codegen() {
209209
return InstantiationMode::LocalCopy;
210210
}
211211

‎compiler/rustc_mir_transform/src/cross_crate_inline.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
4646
// #[inline(never)] to force code generation.
4747
match codegen_fn_attrs.inline {
4848
InlineAttr::Never => return false,
49-
InlineAttr::Hint | InlineAttr::Always | InlineAttr::Force { .. } => return true,
50-
_ => {}
49+
InlineAttr::Hint | InlineAttr::Always | InlineAttr::Early | InlineAttr::Force { .. } => {
50+
return true;
51+
}
52+
InlineAttr::None => {}
5153
}
5254

5355
// If the crate is likely to be mostly unused, use cross-crate inlining to defer codegen until
@@ -77,7 +79,7 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
7779
// enabled. This ensures that we do inference even if someone only passes -Zinline-mir,
7880
// which is less confusing than having to also enable -Copt-level=1.
7981
let inliner_will_run = pm::should_run_pass(tcx, &inline::Inline, pm::Optimizations::Allowed)
80-
|| inline::ForceInline::should_run_pass_for_callee(tcx, def_id.to_def_id());
82+
|| inline::ForceInline::applies_for_resolved_callee(tcx, def_id.to_def_id());
8183
if matches!(tcx.sess.opts.optimize, OptLevel::No) && !inliner_will_run {
8284
return false;
8385
}

‎compiler/rustc_mir_transform/src/inline.rs

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,13 @@ impl<'tcx> crate::MirPass<'tcx> for Inline {
7676
pub struct ForceInline;
7777

7878
impl ForceInline {
79-
pub fn should_run_pass_for_callee<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
79+
pub fn needs_callgraph_for_callee<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
8080
matches!(tcx.codegen_fn_attrs(def_id).inline, InlineAttr::Force { .. })
8181
}
82+
83+
pub fn applies_for_resolved_callee<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
84+
matches!(tcx.codegen_fn_attrs(def_id).inline, InlineAttr::Force { .. } | InlineAttr::Early)
85+
}
8286
}
8387

8488
impl<'tcx> crate::MirPass<'tcx> for ForceInline {
@@ -117,7 +121,7 @@ trait Inliner<'tcx> {
117121
fn changed(self) -> bool;
118122

119123
/// Should inlining happen for a given callee?
120-
fn should_inline_for_callee(&self, def_id:DefId) -> bool;
124+
fn should_inline_for_callee(&self, instance_kind:&InstanceKind<'tcx>) -> bool;
121125

122126
fn check_codegen_attributes_extra(
123127
&self,
@@ -187,15 +191,22 @@ impl<'tcx> Inliner<'tcx> for ForceInliner<'tcx> {
187191
self.changed
188192
}
189193

190-
fn should_inline_for_callee(&self, def_id: DefId) -> bool {
191-
ForceInline::should_run_pass_for_callee(self.tcx(), def_id)
194+
fn should_inline_for_callee(&self, instance_kind: &InstanceKind<'tcx>) -> bool {
195+
if let InstanceKind::Item(def_id) = instance_kind
196+
&& let InlineAttr::Force { .. } | InlineAttr::Early =
197+
self.tcx().codegen_fn_attrs(def_id).inline
198+
{
199+
true
200+
} else {
201+
false
202+
}
192203
}
193204

194205
fn check_codegen_attributes_extra(
195206
&self,
196207
callee_attrs: &CodegenFnAttrs,
197208
) -> Result<(), &'static str> {
198-
debug_assert_matches!(callee_attrs.inline, InlineAttr::Force { .. });
209+
debug_assert_matches!(callee_attrs.inline, InlineAttr::Force { .. } | InlineAttr::Early);
199210
Ok(())
200211
}
201212

@@ -247,23 +258,26 @@ impl<'tcx> Inliner<'tcx> for ForceInliner<'tcx> {
247258

248259
fn on_inline_failure(&self, callsite: &CallSite<'tcx>, reason: &'static str) {
249260
let tcx = self.tcx();
250-
let InlineAttr::Force { attr_span, reason: justification } =
251-
tcx.codegen_fn_attrs(callsite.callee.def_id()).inline
252-
else {
253-
bug!("called on item without required inlining");
254-
};
255-
256-
let call_span = callsite.source_info.span;
257-
tcx.dcx().emit_err(crate::errors::ForceInlineFailure {
258-
call_span,
259-
attr_span,
260-
caller_span: tcx.def_span(self.def_id),
261-
caller: tcx.def_path_str(self.def_id),
262-
callee_span: tcx.def_span(callsite.callee.def_id()),
263-
callee: tcx.def_path_str(callsite.callee.def_id()),
264-
reason,
265-
justification: justification.map(|sym| crate::errors::ForceInlineJustification { sym }),
266-
});
261+
match tcx.codegen_fn_attrs(callsite.callee.def_id()).inline {
262+
InlineAttr::Early => {
263+
// Ok, we don't actually mind if this fails.
264+
}
265+
InlineAttr::Force { attr_span, reason: justification } => {
266+
let call_span = callsite.source_info.span;
267+
tcx.dcx().emit_err(crate::errors::ForceInlineFailure {
268+
call_span,
269+
attr_span,
270+
caller_span: tcx.def_span(self.def_id),
271+
caller: tcx.def_path_str(self.def_id),
272+
callee_span: tcx.def_span(callsite.callee.def_id()),
273+
callee: tcx.def_path_str(callsite.callee.def_id()),
274+
reason,
275+
justification: justification
276+
.map(|sym| crate::errors::ForceInlineJustification { sym }),
277+
});
278+
}
279+
_ => bug!("called on item without required inlining"),
280+
}
267281
}
268282
}
269283

@@ -334,7 +348,7 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> {
334348
self.changed
335349
}
336350

337-
fn should_inline_for_callee(&self, _: DefId) -> bool {
351+
fn should_inline_for_callee(&self, _: &InstanceKind<'tcx>) -> bool {
338352
true
339353
}
340354

@@ -556,16 +570,16 @@ fn resolve_callsite<'tcx, I: Inliner<'tcx>>(
556570
if let TerminatorKind::Call { ref func, fn_span, .. } = terminator.kind {
557571
let func_ty = func.ty(caller_body, tcx);
558572
if let ty::FnDef(def_id, args) = *func_ty.kind() {
559-
if !inliner.should_inline_for_callee(def_id) {
560-
debug!("not enabled");
561-
return None;
562-
}
563-
564573
// To resolve an instance its args have to be fully normalized.
565574
let args = tcx.try_normalize_erasing_regions(inliner.typing_env(), args).ok()?;
566575
let callee =
567576
Instance::try_resolve(tcx, inliner.typing_env(), def_id, args).ok().flatten()?;
568577

578+
if !inliner.should_inline_for_callee(&callee.def) {
579+
debug!("not enabled");
580+
return None;
581+
}
582+
569583
if let InstanceKind::Virtual(..) | InstanceKind::Intrinsic(_) = callee.def {
570584
return None;
571585
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /