Skip to content

Commit 0c8e080

Browse files
committed
mir_transform: adjust inlining failure reasons
1 parent 9c66b20 commit 0c8e080

File tree

2 files changed

+38
-19
lines changed

2 files changed

+38
-19
lines changed

compiler/rustc_attr/src/builtin.rs

+7
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ pub enum InlineAttr {
6262
}
6363

6464
impl InlineAttr {
65+
pub fn required(&self) -> bool {
66+
match self {
67+
InlineAttr::Must { .. } | InlineAttr::Required { .. } => true,
68+
InlineAttr::None | InlineAttr::Hint | InlineAttr::Always | InlineAttr::Never => false,
69+
}
70+
}
71+
6572
pub fn always(&self) -> bool {
6673
match self {
6774
InlineAttr::Always | InlineAttr::Must { .. } | InlineAttr::Required { .. } => true,

compiler/rustc_mir_transform/src/inline.rs

+31-19
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ pub fn should_run_pass_for_item<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> bool {
7474
}
7575

7676
let codegen_fn_attrs = tcx.codegen_fn_attrs(did);
77-
matches!(codegen_fn_attrs.inline, InlineAttr::Required { .. } | InlineAttr::Must { .. })
77+
codegen_fn_attrs.inline.required()
7878
|| match tcx.sess.mir_opt_level() {
7979
0 | 1 => false,
8080
2 => {
@@ -219,8 +219,10 @@ impl<'tcx> Inliner<'tcx> {
219219
// Intrinsic fallback bodies are automatically made cross-crate inlineable,
220220
// but at this stage we don't know whether codegen knows the intrinsic,
221221
// so just conservatively don't inline it.
222-
if self.tcx.has_attr(callsite.callee.def_id(), sym::rustc_intrinsic) {
223-
return Err("Callee is an intrinsic, do not inline fallback bodies");
222+
if self.tcx.has_attr(callsite.callee.def_id(), sym::rustc_intrinsic)
223+
&& !callee_attrs.inline.required()
224+
{
225+
return Err("callee is an intrinsic");
224226
}
225227

226228
let terminator = caller_body[callsite.block].terminator.as_ref().unwrap();
@@ -230,7 +232,7 @@ impl<'tcx> Inliner<'tcx> {
230232
if !arg.node.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.param_env) {
231233
// We do not allow inlining functions with unsized params. Inlining these functions
232234
// could create unsized locals, which are unsound and being phased out.
233-
return Err("Call has unsized argument");
235+
return Err("call has unsized argument");
234236
}
235237
}
236238

@@ -239,7 +241,8 @@ impl<'tcx> Inliner<'tcx> {
239241

240242
if !self.tcx.consider_optimizing(|| {
241243
format!("Inline {:?} into {:?}", callsite.callee, caller_body.source)
242-
}) {
244+
}) && !callee_attrs.inline.required()
245+
{
243246
return Err("optimization fuel exhausted");
244247
}
245248

@@ -248,7 +251,8 @@ impl<'tcx> Inliner<'tcx> {
248251
self.param_env,
249252
ty::EarlyBinder::bind(callee_body.clone()),
250253
) else {
251-
return Err("failed to normalize callee body");
254+
debug!("failed to normalize callee body");
255+
return Err("implementation limitation");
252256
};
253257

254258
// Normally, this shouldn't be required, but trait normalization failure can create a
@@ -262,7 +266,8 @@ impl<'tcx> Inliner<'tcx> {
262266
)
263267
.is_empty()
264268
{
265-
return Err("failed to validate callee body");
269+
debug!("failed to validate callee body");
270+
return Err("implementation limitation");
266271
}
267272

268273
// Check call signature compatibility.
@@ -272,14 +277,15 @@ impl<'tcx> Inliner<'tcx> {
272277
if !util::relate_types(self.tcx, self.param_env, ty::Covariant, output_type, destination_ty)
273278
{
274279
trace!(?output_type, ?destination_ty);
275-
return Err("failed to normalize return type");
280+
debug!("failed to normalize return type");
281+
return Err("implementation limitation");
276282
}
277283
if callsite.fn_sig.abi() == Abi::RustCall {
278284
// FIXME: Don't inline user-written `extern "rust-call"` functions,
279285
// since this is generally perf-negative on rustc, and we hope that
280286
// LLVM will inline these functions instead.
281287
if callee_body.spread_arg.is_some() {
282-
return Err("do not inline user-written rust-call functions");
288+
return Err("user-written rust-call functions");
283289
}
284290

285291
let (self_arg, arg_tuple) = match &args[..] {
@@ -303,7 +309,8 @@ impl<'tcx> Inliner<'tcx> {
303309
if !util::relate_types(self.tcx, self.param_env, ty::Covariant, input_type, arg_ty)
304310
{
305311
trace!(?arg_ty, ?input_type);
306-
return Err("failed to normalize tuple argument type");
312+
debug!("failed to normalize tuple argument type");
313+
return Err("implementation limitation");
307314
}
308315
}
309316
} else {
@@ -313,7 +320,8 @@ impl<'tcx> Inliner<'tcx> {
313320
if !util::relate_types(self.tcx, self.param_env, ty::Covariant, input_type, arg_ty)
314321
{
315322
trace!(?arg_ty, ?input_type);
316-
return Err("failed to normalize argument type");
323+
debug!("failed to normalize argument type");
324+
return Err("implementation limitation");
317325
}
318326
}
319327
}
@@ -342,12 +350,14 @@ impl<'tcx> Inliner<'tcx> {
342350
// because it has no MIR because it's an extern function), then the inliner
343351
// won't cause cycles on this.
344352
if !self.tcx.is_mir_available(callee_def_id) {
345-
return Err("item MIR unavailable");
353+
debug!("item MIR unavailable");
354+
return Err("implementation limitation");
346355
}
347356
}
348357
// These have no own callable MIR.
349358
InstanceKind::Intrinsic(_) | InstanceKind::Virtual(..) => {
350-
return Err("instance without MIR (intrinsic / virtual)");
359+
debug!("instance without MIR (intrinsic / virtual)");
360+
return Err("implementation limitation");
351361
}
352362

353363
// FIXME(#127030): `ConstParamHasTy` has bad interactions with
@@ -356,7 +366,8 @@ impl<'tcx> Inliner<'tcx> {
356366
// the MIR for this instance until all of its const params are
357367
// substituted.
358368
InstanceKind::DropGlue(_, Some(ty)) if ty.has_type_flags(TypeFlags::HAS_CT_PARAM) => {
359-
return Err("still needs substitution");
369+
debug!("still needs substitution");
370+
return Err("implementation limitation");
360371
}
361372

362373
// This cannot result in an immediate cycle since the callee MIR is a shim, which does
@@ -385,7 +396,8 @@ impl<'tcx> Inliner<'tcx> {
385396
// If we know for sure that the function we're calling will itself try to
386397
// call us, then we avoid inlining that function.
387398
if self.tcx.mir_callgraph_reachable((callee, caller_def_id.expect_local())) {
388-
return Err("caller might be reachable from callee (query cycle avoidance)");
399+
debug!("query cycle avoidance");
400+
return Err("caller might be reachable from callee");
389401
}
390402

391403
Ok(())
@@ -459,7 +471,7 @@ impl<'tcx> Inliner<'tcx> {
459471
}
460472

461473
if let InlineAttr::Never = callee_attrs.inline {
462-
return Err("never inline hint");
474+
return Err("never inline attribute");
463475
}
464476

465477
// FIXME(#127234): Coverage instrumentation currently doesn't handle inlined
@@ -528,12 +540,12 @@ impl<'tcx> Inliner<'tcx> {
528540
let tcx = self.tcx;
529541

530542
if let Some(_) = callee_body.tainted_by_errors {
531-
return Err("Body is tainted");
543+
return Err("body has errors");
532544
}
533545

534546
// Callees which require inlining must be inlined to maintain security properties or
535547
// for performance reasons, so skip any heuristics.
536-
if matches!(callee_attrs.inline, InlineAttr::Required { .. } | InlineAttr::Must { .. }) {
548+
if callee_attrs.inline.required() {
537549
debug!("INLINING {:?} [required]", callsite);
538550
return Ok(());
539551
}
@@ -594,7 +606,7 @@ impl<'tcx> Inliner<'tcx> {
594606
// assign one. However, during this stage we require an exact match when any
595607
// inline-asm is detected. LLVM will still possibly do an inline later on
596608
// if the no-attribute function ends up with the same instruction set anyway.
597-
return Err("Cannot move inline-asm across instruction sets");
609+
return Err("cannot move inline-asm across instruction sets");
598610
} else if let TerminatorKind::TailCall { .. } = term.kind {
599611
// FIXME(explicit_tail_calls): figure out how exactly functions containing tail
600612
// calls can be inlined (and if they even should)

0 commit comments

Comments
 (0)