@@ -14,7 +14,8 @@ use rustc_data_structures::temp_dir::MaybeTempDir;
1414use rustc_hir as hir;
1515use rustc_hir:: def:: DefKind ;
1616use 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} ;
1920use rustc_hir:: definitions:: DefPathData ;
2021use 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) ;
0 commit comments