Skip to content

Commit d829780

Browse files
committed
Auto merge of #131481 - nnethercote:rm-GenKillSet, r=cjgillot
Remove `GenKillAnalysis` There are two kinds of dataflow analysis in the compiler: `Analysis`, which is the basic kind, and `GenKillAnalysis`, which is a more specialized kind for gen/kill analyses that is intended as an optimization. However, it turns out that `GenKillAnalysis` is actually a pessimization! It's faster (and much simpler) to do all the gen/kill analyses via `Analysis`. This lets us remove `GenKillAnalysis`, and `GenKillSet`, and a few other things, and also merge `AnalysisDomain` into `Analysis`. The PR removes 500 lines of code and improves performance. r? `@tmiasko`
2 parents 1f67a7a + 33abf6a commit d829780

File tree

17 files changed

+161
-657
lines changed

17 files changed

+161
-657
lines changed

Diff for: compiler/rustc_borrowck/src/dataflow.rs

+25-39
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
use rustc_data_structures::fx::FxIndexMap;
22
use rustc_data_structures::graph;
33
use rustc_index::bit_set::BitSet;
4-
use rustc_middle::mir::{
5-
self, BasicBlock, Body, CallReturnPlaces, Location, Place, TerminatorEdges,
6-
};
4+
use rustc_middle::mir::{self, BasicBlock, Body, Location, Place, TerminatorEdges};
75
use rustc_middle::ty::{RegionVid, TyCtxt};
86
use rustc_mir_dataflow::fmt::DebugWithContext;
97
use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
10-
use rustc_mir_dataflow::{Analysis, AnalysisDomain, Forward, GenKill, Results, ResultsVisitable};
8+
use rustc_mir_dataflow::{Analysis, Forward, GenKill, Results, ResultsVisitable};
119
use tracing::debug;
1210

1311
use crate::{BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, places_conflict};
@@ -22,9 +20,9 @@ pub(crate) struct BorrowckResults<'a, 'tcx> {
2220
/// The transient state of the dataflow analyses used by the borrow checker.
2321
#[derive(Debug)]
2422
pub(crate) struct BorrowckDomain<'a, 'tcx> {
25-
pub(crate) borrows: <Borrows<'a, 'tcx> as AnalysisDomain<'tcx>>::Domain,
26-
pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'tcx> as AnalysisDomain<'tcx>>::Domain,
27-
pub(crate) ever_inits: <EverInitializedPlaces<'a, 'tcx> as AnalysisDomain<'tcx>>::Domain,
23+
pub(crate) borrows: <Borrows<'a, 'tcx> as Analysis<'tcx>>::Domain,
24+
pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'tcx> as Analysis<'tcx>>::Domain,
25+
pub(crate) ever_inits: <EverInitializedPlaces<'a, 'tcx> as Analysis<'tcx>>::Domain,
2826
}
2927

3028
impl<'a, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'tcx> {
@@ -427,7 +425,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
427425
/// That means they went out of a nonlexical scope
428426
fn kill_loans_out_of_scope_at_location(
429427
&self,
430-
trans: &mut impl GenKill<BorrowIndex>,
428+
trans: &mut <Self as Analysis<'tcx>>::Domain,
431429
location: Location,
432430
) {
433431
// NOTE: The state associated with a given `location`
@@ -447,7 +445,11 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
447445
}
448446

449447
/// Kill any borrows that conflict with `place`.
450-
fn kill_borrows_on_place(&self, trans: &mut impl GenKill<BorrowIndex>, place: Place<'tcx>) {
448+
fn kill_borrows_on_place(
449+
&self,
450+
trans: &mut <Self as Analysis<'tcx>>::Domain,
451+
place: Place<'tcx>,
452+
) {
451453
debug!("kill_borrows_on_place: place={:?}", place);
452454

453455
let other_borrows_of_local = self
@@ -486,7 +488,14 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
486488
}
487489
}
488490

489-
impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
491+
/// Forward dataflow computation of the set of borrows that are in scope at a particular location.
492+
/// - we gen the introduced loans
493+
/// - we kill loans on locals going out of (regular) scope
494+
/// - we kill the loans going out of their region's NLL scope: in NLL terms, the frontier where a
495+
/// region stops containing the CFG points reachable from the issuing location.
496+
/// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of
497+
/// `a.b.c` when `a` is overwritten.
498+
impl<'tcx> rustc_mir_dataflow::Analysis<'tcx> for Borrows<'_, 'tcx> {
490499
type Domain = BitSet<BorrowIndex>;
491500

492501
const NAME: &'static str = "borrows";
@@ -500,34 +509,19 @@ impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
500509
// no borrows of code region_scopes have been taken prior to
501510
// function execution, so this method has no effect.
502511
}
503-
}
504-
505-
/// Forward dataflow computation of the set of borrows that are in scope at a particular location.
506-
/// - we gen the introduced loans
507-
/// - we kill loans on locals going out of (regular) scope
508-
/// - we kill the loans going out of their region's NLL scope: in NLL terms, the frontier where a
509-
/// region stops containing the CFG points reachable from the issuing location.
510-
/// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of
511-
/// `a.b.c` when `a` is overwritten.
512-
impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
513-
type Idx = BorrowIndex;
514-
515-
fn domain_size(&self, _: &mir::Body<'tcx>) -> usize {
516-
self.borrow_set.len()
517-
}
518512

519-
fn before_statement_effect(
513+
fn apply_before_statement_effect(
520514
&mut self,
521-
trans: &mut impl GenKill<Self::Idx>,
515+
trans: &mut Self::Domain,
522516
_statement: &mir::Statement<'tcx>,
523517
location: Location,
524518
) {
525519
self.kill_loans_out_of_scope_at_location(trans, location);
526520
}
527521

528-
fn statement_effect(
522+
fn apply_statement_effect(
529523
&mut self,
530-
trans: &mut impl GenKill<Self::Idx>,
524+
trans: &mut Self::Domain,
531525
stmt: &mir::Statement<'tcx>,
532526
location: Location,
533527
) {
@@ -573,7 +567,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
573567
}
574568
}
575569

576-
fn before_terminator_effect(
570+
fn apply_before_terminator_effect(
577571
&mut self,
578572
trans: &mut Self::Domain,
579573
_terminator: &mir::Terminator<'tcx>,
@@ -582,7 +576,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
582576
self.kill_loans_out_of_scope_at_location(trans, location);
583577
}
584578

585-
fn terminator_effect<'mir>(
579+
fn apply_terminator_effect<'mir>(
586580
&mut self,
587581
trans: &mut Self::Domain,
588582
terminator: &'mir mir::Terminator<'tcx>,
@@ -599,14 +593,6 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
599593
}
600594
terminator.edges()
601595
}
602-
603-
fn call_return_effect(
604-
&mut self,
605-
_trans: &mut Self::Domain,
606-
_block: mir::BasicBlock,
607-
_return_places: CallReturnPlaces<'_, 'tcx>,
608-
) {
609-
}
610596
}
611597

612598
impl<C> DebugWithContext<C> for BorrowIndex {}

Diff for: compiler/rustc_const_eval/src/check_consts/resolver.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_middle::mir::{
1111
self, BasicBlock, CallReturnPlaces, Local, Location, Statement, StatementKind, TerminatorEdges,
1212
};
1313
use rustc_mir_dataflow::fmt::DebugWithContext;
14-
use rustc_mir_dataflow::{Analysis, AnalysisDomain, JoinSemiLattice};
14+
use rustc_mir_dataflow::{Analysis, JoinSemiLattice};
1515

1616
use super::{ConstCx, Qualif, qualifs};
1717

@@ -310,7 +310,7 @@ impl JoinSemiLattice for State {
310310
}
311311
}
312312

313-
impl<'tcx, Q> AnalysisDomain<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
313+
impl<'tcx, Q> Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
314314
where
315315
Q: Qualif,
316316
{
@@ -328,12 +328,7 @@ where
328328
fn initialize_start_block(&self, _body: &mir::Body<'tcx>, state: &mut Self::Domain) {
329329
self.transfer_function(state).initialize_state();
330330
}
331-
}
332331

333-
impl<'tcx, Q> Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
334-
where
335-
Q: Qualif,
336-
{
337332
fn apply_statement_effect(
338333
&mut self,
339334
state: &mut Self::Domain,

Diff for: compiler/rustc_middle/src/mir/basic_blocks.rs

-7
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[Option<u128>;
2626
struct Cache {
2727
predecessors: OnceLock<Predecessors>,
2828
switch_sources: OnceLock<SwitchSources>,
29-
is_cyclic: OnceLock<bool>,
3029
reverse_postorder: OnceLock<Vec<BasicBlock>>,
3130
dominators: OnceLock<Dominators<BasicBlock>>,
3231
}
@@ -37,12 +36,6 @@ impl<'tcx> BasicBlocks<'tcx> {
3736
BasicBlocks { basic_blocks, cache: Cache::default() }
3837
}
3938

40-
/// Returns true if control-flow graph contains a cycle reachable from the `START_BLOCK`.
41-
#[inline]
42-
pub fn is_cfg_cyclic(&self) -> bool {
43-
*self.cache.is_cyclic.get_or_init(|| graph::is_cyclic(self))
44-
}
45-
4639
pub fn dominators(&self) -> &Dominators<BasicBlock> {
4740
self.cache.dominators.get_or_init(|| dominators(self))
4841
}

Diff for: compiler/rustc_mir_dataflow/src/framework/cursor.rs

-11
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use rustc_index::bit_set::BitSet;
77
use rustc_middle::mir::{self, BasicBlock, Location};
88

99
use super::{Analysis, Direction, Effect, EffectIndex, Results};
10-
use crate::framework::BitSetExt;
1110

1211
/// Allows random access inspection of the results of a dataflow analysis.
1312
///
@@ -221,16 +220,6 @@ where
221220
}
222221
}
223222

224-
impl<'mir, 'tcx, A> ResultsCursor<'mir, 'tcx, A>
225-
where
226-
A: crate::GenKillAnalysis<'tcx>,
227-
A::Domain: BitSetExt<A::Idx>,
228-
{
229-
pub fn contains(&self, elem: A::Idx) -> bool {
230-
self.get().contains(elem)
231-
}
232-
}
233-
234223
#[derive(Clone, Copy, Debug)]
235224
struct CursorPosition {
236225
block: BasicBlock,

Diff for: compiler/rustc_mir_dataflow/src/framework/direction.rs

+8-58
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_middle::mir::{
55
};
66

77
use super::visitor::{ResultsVisitable, ResultsVisitor};
8-
use super::{Analysis, Effect, EffectIndex, GenKillAnalysis, GenKillSet, SwitchIntTarget};
8+
use super::{Analysis, Effect, EffectIndex, SwitchIntTarget};
99

1010
pub trait Direction {
1111
const IS_FORWARD: bool;
@@ -29,19 +29,10 @@ pub trait Direction {
2929
state: &mut A::Domain,
3030
block: BasicBlock,
3131
block_data: &'mir mir::BasicBlockData<'tcx>,
32-
statement_effect: Option<&dyn Fn(BasicBlock, &mut A::Domain)>,
3332
) -> TerminatorEdges<'mir, 'tcx>
3433
where
3534
A: Analysis<'tcx>;
3635

37-
fn gen_kill_statement_effects_in_block<'tcx, A>(
38-
analysis: &mut A,
39-
trans: &mut GenKillSet<A::Idx>,
40-
block: BasicBlock,
41-
block_data: &mir::BasicBlockData<'tcx>,
42-
) where
43-
A: GenKillAnalysis<'tcx>;
44-
4536
fn visit_results_in_block<'mir, 'tcx, D, R>(
4637
state: &mut D,
4738
block: BasicBlock,
@@ -73,7 +64,6 @@ impl Direction for Backward {
7364
state: &mut A::Domain,
7465
block: BasicBlock,
7566
block_data: &'mir mir::BasicBlockData<'tcx>,
76-
statement_effect: Option<&dyn Fn(BasicBlock, &mut A::Domain)>,
7767
) -> TerminatorEdges<'mir, 'tcx>
7868
where
7969
A: Analysis<'tcx>,
@@ -82,31 +72,12 @@ impl Direction for Backward {
8272
let location = Location { block, statement_index: block_data.statements.len() };
8373
analysis.apply_before_terminator_effect(state, terminator, location);
8474
let edges = analysis.apply_terminator_effect(state, terminator, location);
85-
if let Some(statement_effect) = statement_effect {
86-
statement_effect(block, state)
87-
} else {
88-
for (statement_index, statement) in block_data.statements.iter().enumerate().rev() {
89-
let location = Location { block, statement_index };
90-
analysis.apply_before_statement_effect(state, statement, location);
91-
analysis.apply_statement_effect(state, statement, location);
92-
}
93-
}
94-
edges
95-
}
96-
97-
fn gen_kill_statement_effects_in_block<'tcx, A>(
98-
analysis: &mut A,
99-
trans: &mut GenKillSet<A::Idx>,
100-
block: BasicBlock,
101-
block_data: &mir::BasicBlockData<'tcx>,
102-
) where
103-
A: GenKillAnalysis<'tcx>,
104-
{
10575
for (statement_index, statement) in block_data.statements.iter().enumerate().rev() {
10676
let location = Location { block, statement_index };
107-
analysis.before_statement_effect(trans, statement, location);
108-
analysis.statement_effect(trans, statement, location);
77+
analysis.apply_before_statement_effect(state, statement, location);
78+
analysis.apply_statement_effect(state, statement, location);
10979
}
80+
edges
11081
}
11182

11283
fn apply_effects_in_range<'tcx, A>(
@@ -330,42 +301,21 @@ impl Direction for Forward {
330301
state: &mut A::Domain,
331302
block: BasicBlock,
332303
block_data: &'mir mir::BasicBlockData<'tcx>,
333-
statement_effect: Option<&dyn Fn(BasicBlock, &mut A::Domain)>,
334304
) -> TerminatorEdges<'mir, 'tcx>
335305
where
336306
A: Analysis<'tcx>,
337307
{
338-
if let Some(statement_effect) = statement_effect {
339-
statement_effect(block, state)
340-
} else {
341-
for (statement_index, statement) in block_data.statements.iter().enumerate() {
342-
let location = Location { block, statement_index };
343-
analysis.apply_before_statement_effect(state, statement, location);
344-
analysis.apply_statement_effect(state, statement, location);
345-
}
308+
for (statement_index, statement) in block_data.statements.iter().enumerate() {
309+
let location = Location { block, statement_index };
310+
analysis.apply_before_statement_effect(state, statement, location);
311+
analysis.apply_statement_effect(state, statement, location);
346312
}
347-
348313
let terminator = block_data.terminator();
349314
let location = Location { block, statement_index: block_data.statements.len() };
350315
analysis.apply_before_terminator_effect(state, terminator, location);
351316
analysis.apply_terminator_effect(state, terminator, location)
352317
}
353318

354-
fn gen_kill_statement_effects_in_block<'tcx, A>(
355-
analysis: &mut A,
356-
trans: &mut GenKillSet<A::Idx>,
357-
block: BasicBlock,
358-
block_data: &mir::BasicBlockData<'tcx>,
359-
) where
360-
A: GenKillAnalysis<'tcx>,
361-
{
362-
for (statement_index, statement) in block_data.statements.iter().enumerate() {
363-
let location = Location { block, statement_index };
364-
analysis.before_statement_effect(trans, statement, location);
365-
analysis.statement_effect(trans, statement, location);
366-
}
367-
}
368-
369319
fn apply_effects_in_range<'tcx, A>(
370320
analysis: &mut A,
371321
state: &mut A::Domain,

0 commit comments

Comments
 (0)