diff options
| author | Jonas Schievink <jonasschievink@gmail.com> | 2020-05-26 21:39:24 +0200 |
|---|---|---|
| committer | Jonas Schievink <jonasschievink@gmail.com> | 2020-09-18 21:23:01 +0200 |
| commit | ddd6930b549d069ac13de66b8676fed4feb95ec4 (patch) | |
| tree | 05cfa2d1f72b4e537e417a9c1b1c37ff60100f1b | |
| parent | ab26fb140c9225c690a219c055a54eba57188d4a (diff) | |
| download | rust-ddd6930b549d069ac13de66b8676fed4feb95ec4.tar.gz rust-ddd6930b549d069ac13de66b8676fed4feb95ec4.zip | |
perf: bail out when there's >500 candidate locals
| -rw-r--r-- | compiler/rustc_mir/src/transform/dest_prop.rs | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs index d22c11f491b..cb4321ace7f 100644 --- a/compiler/rustc_mir/src/transform/dest_prop.rs +++ b/compiler/rustc_mir/src/transform/dest_prop.rs @@ -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(), |
