@@ -9,6 +9,7 @@ use rustc_const_eval::interpret::{
9
9
} ;
10
10
use rustc_hir:: def:: DefKind ;
11
11
use rustc_hir:: HirId ;
12
+ use rustc_index:: bit_set:: BitSet ;
12
13
use rustc_middle:: mir:: visit:: Visitor ;
13
14
use rustc_middle:: mir:: * ;
14
15
use rustc_middle:: ty:: layout:: { LayoutError , LayoutOf , LayoutOfHelpers , TyAndLayout } ;
@@ -129,6 +130,8 @@ struct ConstPropagator<'mir, 'tcx> {
129
130
ecx : InterpCx < ' mir , ' tcx , ConstPropMachine < ' mir , ' tcx > > ,
130
131
tcx : TyCtxt < ' tcx > ,
131
132
param_env : ParamEnv < ' tcx > ,
133
+ worklist : Vec < BasicBlock > ,
134
+ visited_blocks : BitSet < BasicBlock > ,
132
135
}
133
136
134
137
impl < ' tcx > LayoutOfHelpers < ' tcx > for ConstPropagator < ' _ , ' tcx > {
@@ -203,7 +206,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
203
206
)
204
207
. expect ( "failed to push initial stack frame" ) ;
205
208
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
+ }
207
216
}
208
217
209
218
fn body ( & self ) -> & ' mir Body < ' tcx > {
@@ -496,12 +505,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
496
505
if expected != value_const {
497
506
// Poison all places this operand references so that further code
498
507
// 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 ) ;
504
510
}
511
+
505
512
enum DbgVal < T > {
506
513
Val ( T ) ,
507
514
Underscore ,
@@ -566,7 +573,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
566
573
567
574
impl < ' tcx > Visitor < ' tcx > for ConstPropagator < ' _ , ' tcx > {
568
575
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] ;
570
582
self . visit_basic_block_data ( bb, data) ;
571
583
}
572
584
}
@@ -657,6 +669,17 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
657
669
TerminatorKind :: Assert { expected, ref msg, ref cond, .. } => {
658
670
self . check_assertion ( * expected, msg, cond, location) ;
659
671
}
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
+ }
660
683
// None of these have Operands to const-propagate.
661
684
TerminatorKind :: Goto { .. }
662
685
| TerminatorKind :: Resume
@@ -668,10 +691,11 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
668
691
| TerminatorKind :: GeneratorDrop
669
692
| TerminatorKind :: FalseEdge { .. }
670
693
| TerminatorKind :: FalseUnwind { .. }
671
- | TerminatorKind :: SwitchInt { .. }
672
694
| TerminatorKind :: Call { .. }
673
695
| TerminatorKind :: InlineAsm { .. } => { }
674
696
}
697
+
698
+ self . worklist . extend ( terminator. successors ( ) ) ;
675
699
}
676
700
677
701
fn visit_basic_block_data ( & mut self , block : BasicBlock , data : & BasicBlockData < ' tcx > ) {
0 commit comments