Skip to content

Commit 7d47a91

Browse files
committed
Only visit reachable blocks in ConstProp lint.
1 parent f8cfafc commit 7d47a91

File tree

3 files changed

+48
-8
lines changed

3 files changed

+48
-8
lines changed

compiler/rustc_mir_transform/src/const_prop_lint.rs

+32-8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use rustc_const_eval::interpret::{
99
};
1010
use rustc_hir::def::DefKind;
1111
use rustc_hir::HirId;
12+
use rustc_index::bit_set::BitSet;
1213
use rustc_middle::mir::visit::Visitor;
1314
use rustc_middle::mir::*;
1415
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
@@ -129,6 +130,8 @@ struct ConstPropagator<'mir, 'tcx> {
129130
ecx: InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>,
130131
tcx: TyCtxt<'tcx>,
131132
param_env: ParamEnv<'tcx>,
133+
worklist: Vec<BasicBlock>,
134+
visited_blocks: BitSet<BasicBlock>,
132135
}
133136

134137
impl<'tcx> LayoutOfHelpers<'tcx> for ConstPropagator<'_, 'tcx> {
@@ -203,7 +206,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
203206
)
204207
.expect("failed to push initial stack frame");
205208

206-
ConstPropagator { ecx, tcx, param_env }
209+
ConstPropagator {
210+
ecx,
211+
tcx,
212+
param_env,
213+
worklist: vec![START_BLOCK],
214+
visited_blocks: BitSet::new_empty(body.basic_blocks.len()),
215+
}
207216
}
208217

209218
fn body(&self) -> &'mir Body<'tcx> {
@@ -496,12 +505,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
496505
if expected != value_const {
497506
// Poison all places this operand references so that further code
498507
// doesn't use the invalid value
499-
match cond {
500-
Operand::Move(ref place) | Operand::Copy(ref place) => {
501-
Self::remove_const(&mut self.ecx, place.local);
502-
}
503-
Operand::Constant(_) => {}
508+
if let Some(place) = cond.place() {
509+
Self::remove_const(&mut self.ecx, place.local);
504510
}
511+
505512
enum DbgVal<T> {
506513
Val(T),
507514
Underscore,
@@ -566,7 +573,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
566573

567574
impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
568575
fn visit_body(&mut self, body: &Body<'tcx>) {
569-
for (bb, data) in body.basic_blocks.iter_enumerated() {
576+
while let Some(bb) = self.worklist.pop() {
577+
if !self.visited_blocks.insert(bb) {
578+
continue;
579+
}
580+
581+
let data = &body.basic_blocks[bb];
570582
self.visit_basic_block_data(bb, data);
571583
}
572584
}
@@ -657,6 +669,17 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
657669
TerminatorKind::Assert { expected, ref msg, ref cond, .. } => {
658670
self.check_assertion(*expected, msg, cond, location);
659671
}
672+
TerminatorKind::SwitchInt { ref discr, ref targets } => {
673+
if let Some(ref value) = self.eval_operand(&discr, location)
674+
&& let Some(value_const) = self.use_ecx(location, |this| this.ecx.read_scalar(&value))
675+
&& let Ok(constant) = value_const.try_to_int()
676+
&& let Ok(constant) = constant.to_bits(constant.size())
677+
{
678+
let target = targets.target_for_value(constant);
679+
self.worklist.push(target);
680+
return;
681+
}
682+
}
660683
// None of these have Operands to const-propagate.
661684
TerminatorKind::Goto { .. }
662685
| TerminatorKind::Resume
@@ -668,10 +691,11 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
668691
| TerminatorKind::GeneratorDrop
669692
| TerminatorKind::FalseEdge { .. }
670693
| TerminatorKind::FalseUnwind { .. }
671-
| TerminatorKind::SwitchInt { .. }
672694
| TerminatorKind::Call { .. }
673695
| TerminatorKind::InlineAsm { .. } => {}
674696
}
697+
698+
self.worklist.extend(terminator.successors());
675699
}
676700

677701
fn visit_basic_block_data(&mut self, block: BasicBlock, data: &BasicBlockData<'tcx>) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Use `build-pass` to ensure const-prop lint runs.
2+
// build-pass
3+
4+
fn main() {
5+
[()][if false { 1 } else { return }]
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Use `build-pass` to ensure const-prop lint runs.
2+
// build-pass
3+
4+
fn main() {
5+
let x = 2u32;
6+
let y = 3u32;
7+
if y <= x {
8+
dbg!(x - y);
9+
}
10+
}

0 commit comments

Comments
 (0)