Skip to content

Commit 035eff1

Browse files
authored
Rollup merge of rust-lang#57351 - oli-obk:cheap_const_ops, r=RalfJung
Don't actually create a full MIR stack frame when not needed r? @dotdash This should significantly reduce overhead during const propagation and reduce overhead *after* copy propagation (cc rust-lang#36673)
2 parents 75a369c + dec79e4 commit 035eff1

File tree

1 file changed

+36
-14
lines changed

1 file changed

+36
-14
lines changed

src/librustc_mir/const_eval.rs

+36-14
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ const STEPS_UNTIL_DETECTOR_ENABLED: isize = 1_000_000;
3535
/// Should be a power of two for performance reasons.
3636
const DETECTOR_SNAPSHOT_PERIOD: isize = 256;
3737

38+
/// Warning: do not use this function if you expect to start interpreting the given `Mir`.
39+
/// The `EvalContext` is only meant to be used to query values from constants and statics.
40+
///
41+
/// This function is used during const propagation. We cannot use `mk_eval_cx`, because copy
42+
/// propagation happens *during* the computation of the MIR of the current function. So if we
43+
/// tried to call the `optimized_mir` query, we'd get a cycle error because we are (transitively)
44+
/// inside the `optimized_mir` query of the `Instance` given.
45+
///
46+
/// Since we are looking at the MIR of the function in an abstract manner, we don't have a
47+
/// `ParamEnv` available to us. This function creates a `ParamEnv` for the given instance.
3848
pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
3949
tcx: TyCtxt<'a, 'tcx, 'tcx>,
4050
instance: Instance<'tcx>,
@@ -43,9 +53,22 @@ pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
4353
) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'mir, 'tcx>> {
4454
debug!("mk_borrowck_eval_cx: {:?}", instance);
4555
let param_env = tcx.param_env(instance.def_id());
56+
mk_eval_cx_inner(tcx, instance, mir, span, param_env)
57+
}
58+
59+
/// This is just a helper function to reduce code duplication between `mk_borrowck_eval_cx` and
60+
/// `mk_eval_cx`. Do not call this function directly.
61+
fn mk_eval_cx_inner<'a, 'mir, 'tcx>(
62+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
63+
instance: Instance<'tcx>,
64+
mir: &'mir mir::Mir<'tcx>,
65+
span: Span,
66+
param_env: ty::ParamEnv<'tcx>,
67+
) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'mir, 'tcx>> {
4668
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new());
47-
// insert a stack frame so any queries have the correct substs
48-
// cannot use `push_stack_frame`; if we do `const_prop` explodes
69+
// Insert a stack frame so any queries have the correct substs.
70+
// We also avoid all the extra work performed by push_stack_frame,
71+
// like initializing local variables
4972
ecx.stack.push(interpret::Frame {
5073
block: mir::START_BLOCK,
5174
locals: IndexVec::new(),
@@ -60,24 +83,23 @@ pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
6083
Ok(ecx)
6184
}
6285

63-
pub fn mk_eval_cx<'a, 'tcx>(
86+
/// Warning: do not use this function if you expect to start interpreting the given `Mir`.
87+
/// The `EvalContext` is only meant to be used to do field and index projections into constants for
88+
/// `simd_shuffle` and const patterns in match arms.
89+
///
90+
/// The function containing the `match` that is currently being analyzed may have generic bounds
91+
/// that inform us about the generic bounds of the constant. E.g. using an associated constant
92+
/// of a function's generic parameter will require knowledge about the bounds on the generic
93+
/// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
94+
fn mk_eval_cx<'a, 'tcx>(
6495
tcx: TyCtxt<'a, 'tcx, 'tcx>,
6596
instance: Instance<'tcx>,
6697
param_env: ty::ParamEnv<'tcx>,
6798
) -> EvalResult<'tcx, CompileTimeEvalContext<'a, 'tcx, 'tcx>> {
6899
debug!("mk_eval_cx: {:?}, {:?}", instance, param_env);
69100
let span = tcx.def_span(instance.def_id());
70-
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new());
71-
let mir = ecx.load_mir(instance.def)?;
72-
// insert a stack frame so any queries have the correct substs
73-
ecx.push_stack_frame(
74-
instance,
75-
mir.span,
76-
mir,
77-
None,
78-
StackPopCleanup::Goto(None), // never pop
79-
)?;
80-
Ok(ecx)
101+
let mir = tcx.optimized_mir(instance.def.def_id());
102+
mk_eval_cx_inner(tcx, instance, mir, span, param_env)
81103
}
82104

83105
pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(

0 commit comments

Comments
 (0)