Skip to content

Commit 8575026

Browse files
perf: bail out when there's >500 candidate locals
1 parent 093b248 commit 8575026

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

src/librustc_mir/transform/dest_prop.rs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ use rustc_middle::mir::{
114114
};
115115
use rustc_middle::ty::{self, Ty, TyCtxt};
116116

117+
const MAX_LOCALS: usize = 500;
118+
117119
pub struct DestinationPropagation;
118120

119121
impl<'tcx> MirPass<'tcx> for DestinationPropagation {
@@ -137,7 +139,29 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
137139
relevant_locals.insert(*src);
138140
}
139141

142+
// This pass unfortunately has `O(l² * s)` performance, where `l` is the number of locals
143+
// and `s` is the number of statements and terminators in the function.
144+
// To prevent blowing up compile times too much, we bail out when there are too many locals.
145+
let relevant = relevant_locals.count();
146+
debug!(
147+
"{:?}: {} locals ({} relevant), {} blocks",
148+
source.def_id(),
149+
body.local_decls.len(),
150+
relevant,
151+
body.basic_blocks().len()
152+
);
153+
if relevant > MAX_LOCALS {
154+
warn!(
155+
"too many candidate locals in {:?} ({}, max is {}), not optimizing",
156+
source.def_id(),
157+
relevant,
158+
MAX_LOCALS
159+
);
160+
return;
161+
}
162+
140163
let mut conflicts = Conflicts::build(tcx, body, source, &relevant_locals);
164+
141165
let mut replacements = Replacements::new(body.local_decls.len());
142166
for candidate @ CandidateAssignment { dest, src, loc } in candidates {
143167
// Merge locals that don't conflict.
@@ -392,12 +416,6 @@ impl Conflicts {
392416
// We don't have to look out for locals that have their address taken, since
393417
// `find_candidates` already takes care of that.
394418

395-
debug!(
396-
"Conflicts::build: {}/{} locals relevant",
397-
relevant_locals.count(),
398-
body.local_decls.len()
399-
);
400-
401419
let mut conflicts = BitMatrix::from_row_n(
402420
&BitSet::new_empty(body.local_decls.len()),
403421
body.local_decls.len(),

0 commit comments

Comments
 (0)