Skip to content

Commit

Permalink
Auto merge of rust-lang#122258 - RalfJung:required-fns, r=<try>
Browse files Browse the repository at this point in the history
Draft: monomorphize things from dead code, too

This is another attempt at fixing rust-lang#107503. The previous attempt at rust-lang#112879 seems stuck in figuring out where the perf regression comes from. So here I want to take baby steps to see the impact of each step.

r? `@ghost`
  • Loading branch information
bors committed Mar 9, 2024
2 parents 25ee3c6 + 95318b4 commit f39ef07
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 7 deletions.
7 changes: 6 additions & 1 deletion compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
use crate::ty::print::{pretty_print_const, with_no_trimmed_paths};
use crate::ty::print::{FmtPrinter, Printer};
use crate::ty::visit::TypeVisitableExt;
use crate::ty::{self, List, Ty, TyCtxt};
use crate::ty::{self, Instance, List, Ty, TyCtxt};
use crate::ty::{AdtDef, InstanceDef, UserTypeAnnotationIndex};
use crate::ty::{GenericArg, GenericArgsRef};

Expand Down Expand Up @@ -375,6 +375,9 @@ pub struct Body<'tcx> {
/// We hold in this field all the constants we are not able to evaluate yet.
pub required_consts: Vec<ConstOperand<'tcx>>,

/// Functions that need to monomorphize successfully for this MIR to be well-formed.
pub required_fns: Vec<Instance<'tcx>>,

/// Does this body use generic parameters. This is used for the `ConstEvaluatable` check.
///
/// Note that this does not actually mean that this body is not computable right now.
Expand Down Expand Up @@ -445,6 +448,7 @@ impl<'tcx> Body<'tcx> {
var_debug_info,
span,
required_consts: Vec::new(),
required_fns: Vec::new(),
is_polymorphic: false,
injection_phase: None,
tainted_by_errors,
Expand Down Expand Up @@ -473,6 +477,7 @@ impl<'tcx> Body<'tcx> {
spread_arg: None,
span: DUMMY_SP,
required_consts: Vec::new(),
required_fns: Vec::new(),
var_debug_info: Vec::new(),
is_polymorphic: false,
injection_phase: None,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_mir_build/src/build/custom/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ pub(super) fn build_custom_mir<'tcx>(
var_debug_info: Vec::new(),
span,
required_consts: Vec::new(),
required_fns: Vec::new(),
is_polymorphic: false,
tainted_by_errors: None,
injection_phase: None,
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_mir_transform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,11 +344,14 @@ fn mir_promoted(
}

let mut required_consts = Vec::new();
let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts);
let mut required_fns = Vec::new();
let mut required_consts_visitor =
RequiredConstsVisitor::new(tcx, &body, &mut required_consts, &mut required_fns);
for (bb, bb_data) in traversal::reverse_postorder(&body) {
required_consts_visitor.visit_basic_block_data(bb, bb_data);
}
body.required_consts = required_consts;
body.required_fns = required_fns;

// What we need to run borrowck etc.
let promote_pass = promote_consts::PromoteTemps::default();
Expand Down
46 changes: 41 additions & 5 deletions compiler/rustc_mir_transform/src/required_consts.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
use rustc_hir::LangItem;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{Const, ConstOperand, Location};
use rustc_middle::ty::ConstKind;
use rustc_middle::mir::{self, Const, ConstOperand, Location};
use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, TyCtxt};

pub struct RequiredConstsVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
body: &'a mir::Body<'tcx>,
required_consts: &'a mut Vec<ConstOperand<'tcx>>,
required_fns: &'a mut Vec<Instance<'tcx>>,
}

impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> {
pub fn new(required_consts: &'a mut Vec<ConstOperand<'tcx>>) -> Self {
RequiredConstsVisitor { required_consts }
pub fn new(
tcx: TyCtxt<'tcx>,
body: &'a mir::Body<'tcx>,
required_consts: &'a mut Vec<ConstOperand<'tcx>>,
required_fns: &'a mut Vec<Instance<'tcx>>,
) -> Self {
RequiredConstsVisitor { tcx, body, required_consts, required_fns }
}
}

Expand All @@ -21,7 +30,34 @@ impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
_ => bug!("only ConstKind::Param/Value should be encountered here, got {:#?}", c),
},
Const::Unevaluated(..) => self.required_consts.push(*constant),
Const::Val(..) => {}
Const::Val(_val, ty) => {
// This is how function items get referenced: via zero-sized constants of `FnDef` type
if let ty::FnDef(def_id, args) = ty.kind() {
debug!("adding to required_fns: {def_id:?}");
// FIXME maybe we shouldn't use `Instance`? We can't use `Instance::new`, it is
// for codegen. But `Instance` feels like the right representation... Check what
// the regular collector does.
self.required_fns.push(Instance { def: InstanceDef::Item(*def_id), args });
}
}
}
}

fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) {
self.super_terminator(terminator, location);

match terminator.kind {
// We don't need to handle `Call` as we already handled all function type operands in
// `visit_constant`. But we do need to handle `Drop`.
mir::TerminatorKind::Drop { place, .. } => {
let ty = place.ty(self.body, self.tcx).ty;
let def_id = self.tcx.require_lang_item(LangItem::DropInPlace, None);
let args = self.tcx.mk_args(&[ty.into()]);
// FIXME: same as above (we cannot use `Instance::resolve_drop_in_place` as this is
// still generic).
self.required_fns.push(Instance { def: InstanceDef::Item(def_id), args });
}
_ => {}
}
}
}

0 comments on commit f39ef07

Please sign in to comment.