Create stable metric to measure long computation in Const Eval

This patch adds a `MirPass` that tracks the number of back-edges and
function calls in the CFG, adds a new MIR instruction to increment a
counter every time they are encountered during Const Eval, and emit a
warning if a configured limit is breached.
This commit is contained in:
Bryan Garza
2022-12-20 00:51:17 +00:00
parent c8e6a9e8b6
commit 360db516cc
37 changed files with 233 additions and 9 deletions

View File

@@ -46,6 +46,9 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
/// The recursion limit (cached from `tcx.recursion_limit(())`)
pub recursion_limit: Limit,
pub const_eval_limit: u32,
pub const_eval_counter: u32,
}
// The Phantomdata exists to prevent this type from being `Send`. If it were sent across a thread
@@ -408,6 +411,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
param_env,
memory: Memory::new(),
recursion_limit: tcx.recursion_limit(),
const_eval_limit: 20,
const_eval_counter: 0,
}
}

View File

@@ -293,6 +293,17 @@ where
Prov: Provenance + 'static,
M: Machine<'mir, 'tcx, Provenance = Prov>,
{
pub fn increment_const_eval_counter(&mut self) {
self.const_eval_counter = self.const_eval_counter + 1;
if self.const_eval_counter == self.const_eval_limit {
let mut warn = self.tcx.sess.struct_warn(format!(
"Const eval counter limit ({}) has been crossed",
self.const_eval_limit
));
warn.emit();
}
}
/// Take a value, which represents a (thin or wide) reference, and make it a place.
/// Alignment is just based on the type. This is the inverse of `MemPlace::to_ref()`.
///

View File

@@ -129,6 +129,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// FIXME(#73156): Handle source code coverage in const eval
Coverage(..) => {}
// FIXME(bryangarza): Update this to do some logic!!!
ConstEvalCounter => {
self.increment_const_eval_counter();
}
// Defined to do nothing. These are added by optimization passes, to avoid changing the
// size of MIR constantly.
Nop => {}