Skip to content

Commit 65b4482

Browse files
committed
Auto merge of #71006 - ecstatic-morse:dataflow-bidi, r=ecstatic-morse
Use existing framework for backward dataflow analyses This PR adds support for backward analyses to the dataflow framework and adds a new live variable analysis (based on the existing one in `librustc_mir/util/liveness.rs`). By adding these to the framework instead of having a separate API, all newly implemented backward dataflow analyses get cursors/visitors, `rustc_peek` tests, and graphviz visualizations for free. In the near-term, this makes it much easier to implement global dead-store elimination, and I believe that this will enable even more MIR optimizations in the future. This PR makes many changes to the dataflow API, since some concepts and terminology only make sense in forward dataflow. Below is a list of the important changes. - ~~`entry_set` -> `fixpoint` (the fixpoint for backward dataflow problems is after the block's terminator)~~ - `seek_{before,after}` -> `seek_{before,after}_primary_effect` (the unprefixed dataflow effect is now referred to as the "primary" effect instead of the "after" effect. The "before" effect remains the same, although I considered changing it to the "antecedent" effect. In both backward and forward dataflow, the "before" effect is applied prior to the "primary" effect. I feel very strongly that this is the correct choice, as it means consumers don't have to switch between `seek_before` and `seek_after` based on the direction of their analysis. - `seek_after_assume_call_returns` is now gone. Users can use `ResultsCursor::apply_custom_effect` to emulate it. - `visit_{statement,terminator}_exit` -> `visit_{statement,terminator}_after_primary_effect` - `visit_{statement,terminator}` -> `visit_{statement,terminator}_before_primary_effect` Implementing this also required refactoring the dataflow cursor implementation so it could work in both directions. This is a large percentage of the diff, since the cursor code is rather complex. The fact that the cursor is exhaustively tested in both directions should reassure whomever is unlucky enough to review this 🤣. In order to avoid computing the reverse CFG for forward dataflow analyses, I've added some hacks to the existing `mir::BodyAndCache` interface. I've requested changes to this interface that would let me implement this more efficiently. r? @eddyb (feel free to reassign) cc @rust-lang/wg-mir-opt
2 parents ea733c3 + 21c72b6 commit 65b4482

File tree

25 files changed

+1369
-709
lines changed

25 files changed

+1369
-709
lines changed

src/librustc_codegen_ssa/mir/analyze.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,8 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
269269

270270
fn visit_local(&mut self, &local: &mir::Local, context: PlaceContext, location: Location) {
271271
match context {
272-
PlaceContext::MutatingUse(MutatingUseContext::Call) => {
272+
PlaceContext::MutatingUse(MutatingUseContext::Call)
273+
| PlaceContext::MutatingUse(MutatingUseContext::Yield) => {
273274
self.assign(local, location);
274275
}
275276

src/librustc_middle/mir/visit.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ macro_rules! make_mir_visitor {
510510
self.visit_operand(value, source_location);
511511
self.visit_place(
512512
resume_arg,
513-
PlaceContext::MutatingUse(MutatingUseContext::Store),
513+
PlaceContext::MutatingUse(MutatingUseContext::Yield),
514514
source_location,
515515
);
516516
}
@@ -1052,6 +1052,8 @@ pub enum MutatingUseContext {
10521052
AsmOutput,
10531053
/// Destination of a call.
10541054
Call,
1055+
/// Destination of a yield.
1056+
Yield,
10551057
/// Being dropped.
10561058
Drop,
10571059
/// Mutable borrow.

src/librustc_mir/borrow_check/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> {
518518
impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx> {
519519
type FlowState = Flows<'cx, 'tcx>;
520520

521-
fn visit_statement(
521+
fn visit_statement_before_primary_effect(
522522
&mut self,
523523
flow_state: &Flows<'cx, 'tcx>,
524524
stmt: &'cx Statement<'tcx>,
@@ -607,7 +607,7 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc
607607
}
608608
}
609609

610-
fn visit_terminator(
610+
fn visit_terminator_before_primary_effect(
611611
&mut self,
612612
flow_state: &Flows<'cx, 'tcx>,
613613
term: &'cx Terminator<'tcx>,
@@ -701,7 +701,7 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc
701701
}
702702
}
703703

704-
fn visit_terminator_exit(
704+
fn visit_terminator_after_primary_effect(
705705
&mut self,
706706
flow_state: &Flows<'cx, 'tcx>,
707707
term: &'cx Terminator<'tcx>,

src/librustc_mir/borrow_check/type_check/liveness/trace.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
408408
/// DROP of some local variable will have an effect -- note that
409409
/// drops, as they may unwind, are always terminators.
410410
fn initialized_at_terminator(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool {
411-
self.flow_inits.seek_before(self.body.terminator_loc(block));
411+
self.flow_inits.seek_before_primary_effect(self.body.terminator_loc(block));
412412
self.initialized_at_curr_loc(mpi)
413413
}
414414

@@ -418,7 +418,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
418418
/// **Warning:** Does not account for the result of `Call`
419419
/// instructions.
420420
fn initialized_at_exit(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool {
421-
self.flow_inits.seek_after(self.body.terminator_loc(block));
421+
self.flow_inits.seek_after_primary_effect(self.body.terminator_loc(block));
422422
self.initialized_at_curr_loc(mpi)
423423
}
424424

0 commit comments

Comments
 (0)