Skip to content

Commit 6c85c49

Browse files
committed
tmp: use polonius loan scopes to see how terribly slow it is
1 parent be4fd06 commit 6c85c49

File tree

3 files changed

+35
-149
lines changed

3 files changed

+35
-149
lines changed

compiler/rustc_borrowck/src/dataflow.rs

+6-120
Original file line numberDiff line numberDiff line change
@@ -131,104 +131,6 @@ struct StackEntry {
131131
lo: usize,
132132
hi: usize,
133133
}
134-
135-
struct OutOfScopePrecomputer<'a, 'tcx> {
136-
visited: BitSet<mir::BasicBlock>,
137-
visit_stack: Vec<StackEntry>,
138-
body: &'a Body<'tcx>,
139-
regioncx: &'a RegionInferenceContext<'tcx>,
140-
borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
141-
}
142-
143-
impl<'a, 'tcx> OutOfScopePrecomputer<'a, 'tcx> {
144-
fn new(body: &'a Body<'tcx>, regioncx: &'a RegionInferenceContext<'tcx>) -> Self {
145-
OutOfScopePrecomputer {
146-
visited: BitSet::new_empty(body.basic_blocks.len()),
147-
visit_stack: vec![],
148-
body,
149-
regioncx,
150-
borrows_out_of_scope_at_location: FxIndexMap::default(),
151-
}
152-
}
153-
}
154-
155-
impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
156-
fn precompute_borrows_out_of_scope(
157-
&mut self,
158-
borrow_index: BorrowIndex,
159-
borrow_region: RegionVid,
160-
first_location: Location,
161-
) {
162-
// We visit one BB at a time. The complication is that we may start in the
163-
// middle of the first BB visited (the one containing `first_location`), in which
164-
// case we may have to later on process the first part of that BB if there
165-
// is a path back to its start.
166-
167-
// For visited BBs, we record the index of the first statement processed.
168-
// (In fully processed BBs this index is 0.) Note also that we add BBs to
169-
// `visited` once they are added to `stack`, before they are actually
170-
// processed, because this avoids the need to look them up again on
171-
// completion.
172-
self.visited.insert(first_location.block);
173-
174-
let first_block = first_location.block;
175-
let mut first_lo = first_location.statement_index;
176-
let first_hi = self.body[first_block].statements.len();
177-
178-
self.visit_stack.push(StackEntry { bb: first_block, lo: first_lo, hi: first_hi });
179-
180-
'preorder: while let Some(StackEntry { bb, lo, hi }) = self.visit_stack.pop() {
181-
if let Some(kill_stmt) =
182-
self.regioncx.first_non_contained_inclusive(borrow_region, bb, lo, hi)
183-
{
184-
let kill_location = Location { block: bb, statement_index: kill_stmt };
185-
// If region does not contain a point at the location, then add to list and skip
186-
// successor locations.
187-
debug!("borrow {:?} gets killed at {:?}", borrow_index, kill_location);
188-
self.borrows_out_of_scope_at_location
189-
.entry(kill_location)
190-
.or_default()
191-
.push(borrow_index);
192-
continue 'preorder;
193-
}
194-
195-
// If we process the first part of the first basic block (i.e. we encounter that block
196-
// for the second time), we no longer have to visit its successors again.
197-
if bb == first_block && hi != first_hi {
198-
continue;
199-
}
200-
201-
// Add successor BBs to the work list, if necessary.
202-
let bb_data = &self.body[bb];
203-
debug_assert!(hi == bb_data.statements.len());
204-
for succ_bb in bb_data.terminator().successors() {
205-
if !self.visited.insert(succ_bb) {
206-
if succ_bb == first_block && first_lo > 0 {
207-
// `succ_bb` has been seen before. If it wasn't
208-
// fully processed, add its first part to `stack`
209-
// for processing.
210-
self.visit_stack.push(StackEntry { bb: succ_bb, lo: 0, hi: first_lo - 1 });
211-
212-
// And update this entry with 0, to represent the
213-
// whole BB being processed.
214-
first_lo = 0;
215-
}
216-
} else {
217-
// succ_bb hasn't been seen before. Add it to
218-
// `stack` for processing.
219-
self.visit_stack.push(StackEntry {
220-
bb: succ_bb,
221-
lo: 0,
222-
hi: self.body[succ_bb].statements.len(),
223-
});
224-
}
225-
}
226-
}
227-
228-
self.visited.clear();
229-
}
230-
}
231-
232134
struct PoloniusOutOfScopePrecomputer<'a, 'tcx> {
233135
visited: BitSet<mir::BasicBlock>,
234136
visit_stack: Vec<StackEntry>,
@@ -455,31 +357,15 @@ pub fn calculate_borrows_out_of_scope_at_location<'tcx>(
455357
regioncx: &RegionInferenceContext<'tcx>,
456358
borrow_set: &BorrowSet<'tcx>,
457359
) -> FxIndexMap<Location, Vec<BorrowIndex>> {
458-
let mut prec = OutOfScopePrecomputer::new(body, regioncx);
459-
for (borrow_index, borrow_data) in borrow_set.iter_enumerated() {
460-
let borrow_region = borrow_data.region;
461-
let location = borrow_data.reserve_location;
360+
let mut polonius_prec = PoloniusOutOfScopePrecomputer::new(body, regioncx);
361+
for (loan_idx, borrow_data) in borrow_set.iter_enumerated() {
362+
let issuing_region = borrow_data.region;
363+
let issued_location = borrow_data.reserve_location;
462364

463-
prec.precompute_borrows_out_of_scope(borrow_index, borrow_region, location);
365+
polonius_prec.precompute_loans_out_of_scope(loan_idx, issuing_region, issued_location);
464366
}
465367

466-
if std::env::var("POLONIUS2").is_ok() {
467-
let mut polonius_prec = PoloniusOutOfScopePrecomputer::new(body, regioncx);
468-
for (loan_idx, borrow_data) in borrow_set.iter_enumerated() {
469-
let issuing_region = borrow_data.region;
470-
let issued_location = borrow_data.reserve_location;
471-
472-
polonius_prec.precompute_loans_out_of_scope(loan_idx, issuing_region, issued_location);
473-
}
474-
475-
assert_eq!(
476-
prec.borrows_out_of_scope_at_location, polonius_prec.borrows_out_of_scope_at_location,
477-
"out of scope borrows and loans differ between polonius and non-polonius mode"
478-
);
479-
polonius_prec.borrows_out_of_scope_at_location
480-
} else {
481-
prec.borrows_out_of_scope_at_location
482-
}
368+
polonius_prec.borrows_out_of_scope_at_location
483369
}
484370

485371
impl<'a, 'tcx> Borrows<'a, 'tcx> {

compiler/rustc_borrowck/src/region_infer/mod.rs

+14-14
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_infer::infer::outlives::test_type_match;
1212
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
1313
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
1414
use rustc_middle::mir::{
15-
BasicBlock, Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureOutlivesSubjectTy,
15+
Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureOutlivesSubjectTy,
1616
ClosureRegionRequirements, ConstraintCategory, Local, Location, ReturnConstraint,
1717
TerminatorKind,
1818
};
@@ -603,19 +603,19 @@ impl<'tcx> RegionInferenceContext<'tcx> {
603603
self.scc_values.contains(scc, p)
604604
}
605605

606-
/// Returns the lowest statement index in `start..=end` which is not contained by `r`.
607-
///
608-
/// Panics if called before `solve()` executes.
609-
pub(crate) fn first_non_contained_inclusive(
610-
&self,
611-
r: RegionVid,
612-
block: BasicBlock,
613-
start: usize,
614-
end: usize,
615-
) -> Option<usize> {
616-
let scc = self.constraint_sccs.scc(r);
617-
self.scc_values.first_non_contained_inclusive(scc, block, start, end)
618-
}
606+
// /// Returns the lowest statement index in `start..=end` which is not contained by `r`.
607+
// ///
608+
// /// Panics if called before `solve()` executes.
609+
// pub(crate) fn first_non_contained_inclusive(
610+
// &self,
611+
// r: RegionVid,
612+
// block: BasicBlock,
613+
// start: usize,
614+
// end: usize,
615+
// ) -> Option<usize> {
616+
// let scc = self.constraint_sccs.scc(r);
617+
// self.scc_values.first_non_contained_inclusive(scc, block, start, end)
618+
// }
619619

620620
/// Returns access to the value of `r` for debugging purposes.
621621
pub(crate) fn region_value_str(&self, r: RegionVid) -> String {

compiler/rustc_borrowck/src/region_infer/values.rs

+15-15
Original file line numberDiff line numberDiff line change
@@ -288,21 +288,21 @@ impl<N: Idx> RegionValues<N> {
288288
elem.contained_in_row(self, r)
289289
}
290290

291-
/// Returns the lowest statement index in `start..=end` which is not contained by `r`.
292-
pub(crate) fn first_non_contained_inclusive(
293-
&self,
294-
r: N,
295-
block: BasicBlock,
296-
start: usize,
297-
end: usize,
298-
) -> Option<usize> {
299-
let row = self.points.row(r)?;
300-
let block = self.elements.entry_point(block);
301-
let start = block.plus(start);
302-
let end = block.plus(end);
303-
let first_unset = row.first_unset_in(start..=end)?;
304-
Some(first_unset.index() - block.index())
305-
}
291+
// /// Returns the lowest statement index in `start..=end` which is not contained by `r`.
292+
// pub(crate) fn first_non_contained_inclusive(
293+
// &self,
294+
// r: N,
295+
// block: BasicBlock,
296+
// start: usize,
297+
// end: usize,
298+
// ) -> Option<usize> {
299+
// let row = self.points.row(r)?;
300+
// let block = self.elements.entry_point(block);
301+
// let start = block.plus(start);
302+
// let end = block.plus(end);
303+
// let first_unset = row.first_unset_in(start..=end)?;
304+
// Some(first_unset.index() - block.index())
305+
// }
306306

307307
/// `self[to] |= values[from]`, essentially: that is, take all the
308308
/// elements for the region `from` from `values` and add them to

0 commit comments

Comments
 (0)