Skip to content

Commit d97a7ce

Browse files
committed
Refactor tracking of writes.
1 parent 9928d0e commit d97a7ce

File tree

2 files changed

+58
-72
lines changed

2 files changed

+58
-72
lines changed

compiler/rustc_mir_transform/src/const_prop.rs

Lines changed: 34 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
use either::Right;
55

66
use rustc_const_eval::const_eval::CheckAlignment;
7-
use rustc_data_structures::fx::FxHashSet;
87
use rustc_hir::def::DefKind;
98
use rustc_index::bit_set::BitSet;
109
use rustc_index::vec::IndexVec;
@@ -152,24 +151,12 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
152151
pub struct ConstPropMachine<'mir, 'tcx> {
153152
/// The virtual call stack.
154153
stack: Vec<Frame<'mir, 'tcx>>,
155-
/// `OnlyInsideOwnBlock` locals that were written in the current block get erased at the end.
156-
pub written_only_inside_own_block_locals: FxHashSet<Local>,
157-
/// Locals that need to be cleared after every block terminates.
158-
pub only_propagate_inside_block_locals: BitSet<Local>,
159154
pub can_const_prop: IndexVec<Local, ConstPropMode>,
160155
}
161156

162157
impl ConstPropMachine<'_, '_> {
163-
pub fn new(
164-
only_propagate_inside_block_locals: BitSet<Local>,
165-
can_const_prop: IndexVec<Local, ConstPropMode>,
166-
) -> Self {
167-
Self {
168-
stack: Vec::new(),
169-
written_only_inside_own_block_locals: Default::default(),
170-
only_propagate_inside_block_locals,
171-
can_const_prop,
172-
}
158+
pub fn new(can_const_prop: IndexVec<Local, ConstPropMode>) -> Self {
159+
Self { stack: Vec::new(), can_const_prop }
173160
}
174161
}
175162

@@ -255,16 +242,14 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
255242
frame: usize,
256243
local: Local,
257244
) -> InterpResult<'tcx, &'a mut interpret::Operand<Self::Provenance>> {
258-
if ecx.machine.can_const_prop[local] == ConstPropMode::NoPropagation {
259-
throw_machine_stop_str!("tried to write to a local that is marked as not propagatable")
260-
}
261-
if frame == 0 && ecx.machine.only_propagate_inside_block_locals.contains(local) {
262-
trace!(
263-
"mutating local {:?} which is restricted to its block. \
264-
Will remove it from const-prop after block is finished.",
265-
local
266-
);
267-
ecx.machine.written_only_inside_own_block_locals.insert(local);
245+
assert_eq!(frame, 0);
246+
match ecx.machine.can_const_prop[local] {
247+
ConstPropMode::NoPropagation => {
248+
throw_machine_stop_str!(
249+
"tried to write to a local that is marked as not propagatable"
250+
)
251+
}
252+
ConstPropMode::OnlyInsideOwnBlock | ConstPropMode::FullConstProp => {}
268253
}
269254
ecx.machine.stack[frame].locals[local].access_mut()
270255
}
@@ -369,17 +354,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
369354
let param_env = tcx.param_env_reveal_all_normalized(def_id);
370355

371356
let can_const_prop = CanConstProp::check(tcx, param_env, body);
372-
let mut only_propagate_inside_block_locals = BitSet::new_empty(can_const_prop.len());
373-
for (l, mode) in can_const_prop.iter_enumerated() {
374-
if *mode == ConstPropMode::OnlyInsideOwnBlock {
375-
only_propagate_inside_block_locals.insert(l);
376-
}
377-
}
378357
let mut ecx = InterpCx::new(
379358
tcx,
380359
tcx.def_span(def_id),
381360
param_env,
382-
ConstPropMachine::new(only_propagate_inside_block_locals, can_const_prop),
361+
ConstPropMachine::new(can_const_prop),
383362
);
384363

385364
let ret_layout = ecx
@@ -977,26 +956,33 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
977956
fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
978957
self.super_basic_block_data(block, data);
979958

959+
let ensure_not_propagated = |this: &mut Self, local: Local| {
960+
if cfg!(debug_assertions) {
961+
assert!(
962+
this.get_const(local.into()).is_none()
963+
|| this
964+
.layout_of(this.local_decls[local].ty)
965+
.map_or(true, |layout| layout.is_zst()),
966+
"failed to remove values for `{local:?}`, value={:?}",
967+
this.get_const(local.into()),
968+
)
969+
}
970+
};
971+
980972
// We remove all Locals which are restricted in propagation to their containing blocks and
981973
// which were modified in the current block.
982974
// Take it out of the ecx so we can get a mutable reference to the ecx for `remove_const`.
983-
let mut locals = std::mem::take(&mut self.ecx.machine.written_only_inside_own_block_locals);
984-
for &local in locals.iter() {
985-
Self::remove_const(&mut self.ecx, local);
986-
}
987-
locals.clear();
988-
// Put it back so we reuse the heap of the storage
989-
self.ecx.machine.written_only_inside_own_block_locals = locals;
990-
if cfg!(debug_assertions) {
991-
// Ensure we are correctly erasing locals with the non-debug-assert logic.
992-
for local in self.ecx.machine.only_propagate_inside_block_locals.iter() {
993-
assert!(
994-
self.get_const(local.into()).is_none()
995-
|| self
996-
.layout_of(self.local_decls[local].ty)
997-
.map_or(true, |layout| layout.is_zst())
998-
)
975+
let can_const_prop = std::mem::take(&mut self.ecx.machine.can_const_prop);
976+
for (local, &mode) in can_const_prop.iter_enumerated() {
977+
match mode {
978+
ConstPropMode::FullConstProp => {}
979+
ConstPropMode::NoPropagation => ensure_not_propagated(self, local),
980+
ConstPropMode::OnlyInsideOwnBlock => {
981+
Self::remove_const(&mut self.ecx, local);
982+
ensure_not_propagated(self, local);
983+
}
999984
}
1000985
}
986+
self.ecx.machine.can_const_prop = can_const_prop;
1001987
}
1002988
}

compiler/rustc_mir_transform/src/const_prop_lint.rs

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use rustc_const_eval::interpret::{
99
};
1010
use rustc_hir::def::DefKind;
1111
use rustc_hir::HirId;
12-
use rustc_index::bit_set::BitSet;
1312
use rustc_index::vec::IndexVec;
1413
use rustc_middle::mir::visit::Visitor;
1514
use rustc_middle::mir::*;
@@ -179,17 +178,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
179178
let param_env = tcx.param_env_reveal_all_normalized(def_id);
180179

181180
let can_const_prop = CanConstProp::check(tcx, param_env, body);
182-
let mut only_propagate_inside_block_locals = BitSet::new_empty(can_const_prop.len());
183-
for (l, mode) in can_const_prop.iter_enumerated() {
184-
if *mode == ConstPropMode::OnlyInsideOwnBlock {
185-
only_propagate_inside_block_locals.insert(l);
186-
}
187-
}
188181
let mut ecx = InterpCx::new(
189182
tcx,
190183
tcx.def_span(def_id),
191184
param_env,
192-
ConstPropMachine::new(only_propagate_inside_block_locals, can_const_prop),
185+
ConstPropMachine::new(can_const_prop),
193186
);
194187

195188
let ret_layout = ecx
@@ -687,26 +680,33 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
687680
fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) {
688681
self.super_basic_block_data(block, data);
689682

683+
let ensure_not_propagated = |this: &mut Self, local: Local| {
684+
if cfg!(debug_assertions) {
685+
assert!(
686+
this.get_const(local.into()).is_none()
687+
|| this
688+
.layout_of(this.local_decls[local].ty)
689+
.map_or(true, |layout| layout.is_zst()),
690+
"failed to remove values for `{local:?}`, value={:?}",
691+
this.get_const(local.into()),
692+
)
693+
}
694+
};
695+
690696
// We remove all Locals which are restricted in propagation to their containing blocks and
691697
// which were modified in the current block.
692698
// Take it out of the ecx so we can get a mutable reference to the ecx for `remove_const`.
693-
let mut locals = std::mem::take(&mut self.ecx.machine.written_only_inside_own_block_locals);
694-
for &local in locals.iter() {
695-
Self::remove_const(&mut self.ecx, local);
696-
}
697-
locals.clear();
698-
// Put it back so we reuse the heap of the storage
699-
self.ecx.machine.written_only_inside_own_block_locals = locals;
700-
if cfg!(debug_assertions) {
701-
// Ensure we are correctly erasing locals with the non-debug-assert logic.
702-
for local in self.ecx.machine.only_propagate_inside_block_locals.iter() {
703-
assert!(
704-
self.get_const(local.into()).is_none()
705-
|| self
706-
.layout_of(self.local_decls[local].ty)
707-
.map_or(true, |layout| layout.is_zst())
708-
)
699+
let can_const_prop = std::mem::take(&mut self.ecx.machine.can_const_prop);
700+
for (local, &mode) in can_const_prop.iter_enumerated() {
701+
match mode {
702+
ConstPropMode::FullConstProp => {}
703+
ConstPropMode::NoPropagation => ensure_not_propagated(self, local),
704+
ConstPropMode::OnlyInsideOwnBlock => {
705+
Self::remove_const(&mut self.ecx, local);
706+
ensure_not_propagated(self, local);
707+
}
709708
}
710709
}
710+
self.ecx.machine.can_const_prop = can_const_prop;
711711
}
712712
}

0 commit comments

Comments
 (0)