Skip to content

Commit d99333e

Browse files
committed
Encode only MIR that can be used by other crates
Only reachable items might participate in the code generation in the downstream crates. Omit redundant optimized MIR of unreachable items from a crate metadata. Additionally, include reachable closures in reachable set, so that unreachable closures can be omitted on the same basis.
1 parent 01ce2d0 commit d99333e

File tree

3 files changed

+36
-13
lines changed

3 files changed

+36
-13
lines changed

compiler/rustc_metadata/src/rmeta/encoder.rs

+31-12
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ use rustc_data_structures::temp_dir::MaybeTempDir;
1414
use rustc_hir as hir;
1515
use rustc_hir::def::DefKind;
1616
use rustc_hir::def_id::{
17-
CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE,
17+
CrateNum, DefId, DefIndex, LocalDefId, LocalDefIdSet, CRATE_DEF_ID, CRATE_DEF_INDEX,
18+
LOCAL_CRATE,
1819
};
1920
use rustc_hir::definitions::DefPathData;
2021
use rustc_hir::lang_items::LangItem;
@@ -50,7 +51,6 @@ pub(super) struct EncodeContext<'a, 'tcx> {
5051
opaque: opaque::FileEncoder,
5152
tcx: TyCtxt<'tcx>,
5253
feat: &'tcx rustc_feature::Features,
53-
5454
tables: TableBuilders,
5555

5656
lazy_state: LazyState,
@@ -1002,15 +1002,31 @@ fn should_encode_stability(def_kind: DefKind) -> bool {
10021002
}
10031003
}
10041004

1005-
/// Whether we should encode MIR.
1005+
/// Whether we should encode MIR. Return a pair, resp. for CTFE and for LLVM.
10061006
///
10071007
/// Computing, optimizing and encoding the MIR is a relatively expensive operation.
10081008
/// We want to avoid this work when not required. Therefore:
10091009
/// - we only compute `mir_for_ctfe` on items with const-eval semantics;
10101010
/// - we skip `optimized_mir` for check runs.
1011+
/// - we only encode `optimized_mir` that could be generated in other crates, that is, a code that
1012+
/// is either generic or has inline hint, and is reachable from the other crates (contained
1013+
/// in reachable set).
1014+
///
1015+
/// Note: Reachable set describes definitions that might be generated or referenced from other
1016+
/// crates and it can be used to limit optimized MIR that needs to be encoded. On the other hand,
1017+
/// the reachable set doesn't have much to say about which definitions might be evaluated at compile
1018+
/// time in other crates, so it cannot be used to omit CTFE MIR. For example, `f` below is
1019+
/// unreachable and yet it can be evaluated in other crates:
10111020
///
1012-
/// Return a pair, resp. for CTFE and for LLVM.
1013-
fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) {
1021+
/// ```
1022+
/// const fn f() -> usize { 0 }
1023+
/// pub struct S { pub a: [usize; f()] }
1024+
/// ```
1025+
fn should_encode_mir(
1026+
tcx: TyCtxt<'_>,
1027+
reachable_set: &LocalDefIdSet,
1028+
def_id: LocalDefId,
1029+
) -> (bool, bool) {
10141030
match tcx.def_kind(def_id) {
10151031
// Constructors
10161032
DefKind::Ctor(_, _) => {
@@ -1027,14 +1043,15 @@ fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) {
10271043
// Full-fledged functions + closures
10281044
DefKind::AssocFn | DefKind::Fn | DefKind::Closure => {
10291045
let generics = tcx.generics_of(def_id);
1030-
let needs_inline = (generics.requires_monomorphization(tcx)
1031-
|| tcx.codegen_fn_attrs(def_id).requests_inline())
1032-
&& tcx.sess.opts.output_types.should_codegen();
1046+
let opt = tcx.sess.opts.unstable_opts.always_encode_mir
1047+
|| (tcx.sess.opts.output_types.should_codegen()
1048+
&& reachable_set.contains(&def_id)
1049+
&& (generics.requires_monomorphization(tcx)
1050+
|| tcx.codegen_fn_attrs(def_id).requests_inline()));
10331051
// The function has a `const` modifier or is in a `#[const_trait]`.
10341052
let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id())
10351053
|| tcx.is_const_default_method(def_id.to_def_id());
1036-
let always_encode_mir = tcx.sess.opts.unstable_opts.always_encode_mir;
1037-
(is_const_fn, needs_inline || always_encode_mir)
1054+
(is_const_fn, opt)
10381055
}
10391056
// Generators require optimized MIR to compute layout.
10401057
DefKind::Generator => (false, true),
@@ -1580,9 +1597,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
15801597
}
15811598

15821599
let tcx = self.tcx;
1600+
let reachable_set = tcx.reachable_set(());
15831601

15841602
let keys_and_jobs = tcx.mir_keys(()).iter().filter_map(|&def_id| {
1585-
let (encode_const, encode_opt) = should_encode_mir(tcx, def_id);
1603+
let (encode_const, encode_opt) = should_encode_mir(tcx, reachable_set, def_id);
15861604
if encode_const || encode_opt { Some((def_id, encode_const, encode_opt)) } else { None }
15871605
});
15881606
for (def_id, encode_const, encode_opt) in keys_and_jobs {
@@ -2067,8 +2085,9 @@ fn prefetch_mir(tcx: TyCtxt<'_>) {
20672085
return;
20682086
}
20692087

2088+
let reachable_set = tcx.reachable_set(());
20702089
par_for_each_in(tcx.mir_keys(()), |&def_id| {
2071-
let (encode_const, encode_opt) = should_encode_mir(tcx, def_id);
2090+
let (encode_const, encode_opt) = should_encode_mir(tcx, reachable_set, def_id);
20722091

20732092
if encode_const {
20742093
tcx.ensure_with_value().mir_for_ctfe(def_id);

compiler/rustc_passes/src/reachable.rs

+4
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> {
9090
.typeck_results()
9191
.type_dependent_def(expr.hir_id)
9292
.map(|(kind, def_id)| Res::Def(kind, def_id)),
93+
hir::ExprKind::Closure(&hir::Closure { def_id, .. }) => {
94+
self.reachable_symbols.insert(def_id);
95+
None
96+
}
9397
_ => None,
9498
};
9599

tests/mir-opt/funky_arms.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use core::num::flt2dec;
99
use std::fmt::{Formatter, Result};
1010

1111
// EMIT_MIR funky_arms.float_to_exponential_common.ConstProp.diff
12-
fn float_to_exponential_common<T>(fmt: &mut Formatter<'_>, num: &T, upper: bool) -> Result
12+
pub fn float_to_exponential_common<T>(fmt: &mut Formatter<'_>, num: &T, upper: bool) -> Result
1313
where
1414
T: flt2dec::DecodableFloat,
1515
{

0 commit comments

Comments
 (0)