perf: bail out when there's >500 candidate locals

This commit is contained in:
Jonas Schievink 2020-05-26 21:39:24 +02:00
parent ab26fb140c
commit ddd6930b54

View File

@ -114,6 +114,8 @@ use rustc_middle::mir::{
};
use rustc_middle::ty::{self, Ty, TyCtxt};
const MAX_LOCALS: usize = 500;
pub struct DestinationPropagation;
impl<'tcx> MirPass<'tcx> for DestinationPropagation {
@ -137,7 +139,29 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
relevant_locals.insert(*src);
}
// This pass unfortunately has `O(l² * s)` performance, where `l` is the number of locals
// and `s` is the number of statements and terminators in the function.
// To prevent blowing up compile times too much, we bail out when there are too many locals.
let relevant = relevant_locals.count();
debug!(
"{:?}: {} locals ({} relevant), {} blocks",
source.def_id(),
body.local_decls.len(),
relevant,
body.basic_blocks().len()
);
if relevant > MAX_LOCALS {
warn!(
"too many candidate locals in {:?} ({}, max is {}), not optimizing",
source.def_id(),
relevant,
MAX_LOCALS
);
return;
}
let mut conflicts = Conflicts::build(tcx, body, source, &relevant_locals);
let mut replacements = Replacements::new(body.local_decls.len());
for candidate @ CandidateAssignment { dest, src, loc } in candidates {
// Merge locals that don't conflict.
@ -392,12 +416,6 @@ impl Conflicts {
// We don't have to look out for locals that have their address taken, since
// `find_candidates` already takes care of that.
debug!(
"Conflicts::build: {}/{} locals relevant",
relevant_locals.count(),
body.local_decls.len()
);
let mut conflicts = BitMatrix::from_row_n(
&BitSet::new_empty(body.local_decls.len()),
body.local_decls.len(),