Skip to content

Commit 3490375

Browse files
committed
Implement SSA-based reference propagation.
1 parent f7b831a commit 3490375

21 files changed

+2668
-80
lines changed

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,6 +1524,19 @@ impl<V, T> ProjectionElem<V, T> {
15241524
}
15251525
}
15261526

1527+
/// Returns `true` if the target of this projection always refers to the same memory region
1528+
/// whatever the state of the program.
1529+
pub fn is_stable_offset(&self) -> bool {
1530+
match self {
1531+
Self::Deref | Self::Index(_) => false,
1532+
Self::Field(_, _)
1533+
| Self::OpaqueCast(_)
1534+
| Self::ConstantIndex { .. }
1535+
| Self::Subslice { .. }
1536+
| Self::Downcast(_, _) => true,
1537+
}
1538+
}
1539+
15271540
/// Returns `true` if this is a `Downcast` projection with the given `VariantIdx`.
15281541
pub fn is_downcast_to(&self, v: VariantIdx) -> bool {
15291542
matches!(*self, Self::Downcast(_, x) if x == v)

compiler/rustc_mir_dataflow/src/impls/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub use self::borrowed_locals::borrowed_locals;
2626
pub use self::borrowed_locals::MaybeBorrowedLocals;
2727
pub use self::liveness::MaybeLiveLocals;
2828
pub use self::liveness::MaybeTransitiveLiveLocals;
29-
pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageLive};
29+
pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageDead, MaybeStorageLive};
3030

3131
/// `MaybeInitializedPlaces` tracks all places that might be
3232
/// initialized upon reaching a particular point in the control flow

compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,72 @@ impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> {
7474
}
7575
}
7676

77+
#[derive(Clone)]
78+
pub struct MaybeStorageDead {
79+
always_live_locals: BitSet<Local>,
80+
}
81+
82+
impl MaybeStorageDead {
83+
pub fn new(always_live_locals: BitSet<Local>) -> Self {
84+
MaybeStorageDead { always_live_locals }
85+
}
86+
}
87+
88+
impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageDead {
89+
type Domain = BitSet<Local>;
90+
91+
const NAME: &'static str = "maybe_storage_dead";
92+
93+
fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
94+
// bottom = live
95+
BitSet::new_empty(body.local_decls.len())
96+
}
97+
98+
fn initialize_start_block(&self, body: &mir::Body<'tcx>, on_entry: &mut Self::Domain) {
99+
assert_eq!(body.local_decls.len(), self.always_live_locals.domain_size());
100+
for local in body.vars_and_temps_iter() {
101+
if !self.always_live_locals.contains(local) {
102+
on_entry.insert(local);
103+
}
104+
}
105+
}
106+
}
107+
108+
impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead {
109+
type Idx = Local;
110+
111+
fn statement_effect(
112+
&self,
113+
trans: &mut impl GenKill<Self::Idx>,
114+
stmt: &mir::Statement<'tcx>,
115+
_: Location,
116+
) {
117+
match stmt.kind {
118+
StatementKind::StorageLive(l) => trans.kill(l),
119+
StatementKind::StorageDead(l) => trans.gen(l),
120+
_ => (),
121+
}
122+
}
123+
124+
fn terminator_effect(
125+
&self,
126+
_trans: &mut impl GenKill<Self::Idx>,
127+
_: &mir::Terminator<'tcx>,
128+
_: Location,
129+
) {
130+
// Terminators have no effect
131+
}
132+
133+
fn call_return_effect(
134+
&self,
135+
_trans: &mut impl GenKill<Self::Idx>,
136+
_block: BasicBlock,
137+
_return_places: CallReturnPlaces<'_, 'tcx>,
138+
) {
139+
// Nothing to do when a call returns successfully
140+
}
141+
}
142+
77143
type BorrowedLocalsResults<'a, 'tcx> = ResultsRefCursor<'a, 'a, 'tcx, MaybeBorrowedLocals>;
78144

79145
/// Dataflow analysis that determines whether each local requires storage at a

compiler/rustc_mir_transform/src/copy_prop.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
7676
fn fully_moved_locals(ssa: &SsaLocals, body: &Body<'_>) -> BitSet<Local> {
7777
let mut fully_moved = BitSet::new_filled(body.local_decls.len());
7878

79-
for (_, rvalue) in ssa.assignments(body) {
79+
for (_, rvalue, _) in ssa.assignments(body) {
8080
let (Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) | Rvalue::CopyForDeref(place))
8181
= rvalue
8282
else { continue };

compiler/rustc_mir_transform/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ mod match_branches;
8484
mod multiple_return_terminators;
8585
mod normalize_array_len;
8686
mod nrvo;
87+
mod ref_prop;
8788
mod remove_noop_landing_pads;
8889
mod remove_storage_markers;
8990
mod remove_uninit_drops;
@@ -559,6 +560,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
559560
&separate_const_switch::SeparateConstSwitch,
560561
&simplify::SimplifyLocals::BeforeConstProp,
561562
&copy_prop::CopyProp,
563+
&ref_prop::ReferencePropagation,
562564
&const_prop::ConstProp,
563565
&dataflow_const_prop::DataflowConstProp,
564566
//

compiler/rustc_mir_transform/src/normalize_array_len.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ fn compute_slice_length<'tcx>(
4141
) -> IndexVec<Local, Option<ty::Const<'tcx>>> {
4242
let mut slice_lengths = IndexVec::from_elem(None, &body.local_decls);
4343

44-
for (local, rvalue) in ssa.assignments(body) {
44+
for (local, rvalue, _) in ssa.assignments(body) {
4545
match rvalue {
4646
Rvalue::Cast(
4747
CastKind::Pointer(ty::adjustment::PointerCast::Unsize),

0 commit comments

Comments
 (0)