1+ use rustc_index:: bit_set:: DenseBitSet ;
12use rustc_middle:: mir:: * ;
23use rustc_middle:: ty:: TyCtxt ;
3- use rustc_mir_dataflow:: impls:: MaybeInitializedPlaces ;
4- use rustc_mir_dataflow:: move_paths:: { LookupResult , MoveData } ;
5- use rustc_mir_dataflow:: { Analysis , MaybeReachable } ;
4+ use rustc_mir_dataflow:: { Analysis , GenKill } ;
65
76use super :: simplify:: simplify_cfg;
87
98pub ( crate ) struct RemoveDeadDrops ;
109
10+ use rustc_middle:: mir:: visit:: * ;
11+
12+ struct MaybeInitializedLocals ;
13+
14+ /// This is conservative: If any part of a local is initialized, we mark it
15+ /// initialized, while we only mark uninitialized if the whole local is moved
16+ /// from or StorageDead.
17+ struct TransferFunction < ' a , T > {
18+ trans : & ' a mut T ,
19+ }
20+
21+ impl < ' tcx , T : GenKill < Local > > Visitor < ' tcx > for TransferFunction < ' _ , T > {
22+ fn visit_place ( & mut self , place : & Place < ' tcx > , context : PlaceContext , location : Location ) {
23+ self . super_place ( place, context, location) ;
24+
25+ if context. is_place_assignment ( ) {
26+ self . trans . gen_ ( place. local ) ;
27+ } else if matches ! (
28+ context,
29+ PlaceContext :: NonUse ( NonUseContext :: StorageLive | NonUseContext :: StorageDead )
30+ ) {
31+ self . trans . kill ( place. local ) ;
32+ }
33+ }
34+
35+ fn visit_operand ( & mut self , operand : & Operand < ' tcx > , location : Location ) {
36+ self . super_operand ( operand, location) ;
37+
38+ if let Operand :: Move ( place) = operand {
39+ if place. projection . is_empty ( ) {
40+ self . trans . kill ( place. local ) ;
41+ }
42+ }
43+ }
44+ }
45+
46+ impl < ' tcx > Analysis < ' tcx > for MaybeInitializedLocals {
47+ type Domain = DenseBitSet < Local > ;
48+ const NAME : & ' static str = "maybe_initialized_locals" ;
49+
50+ fn bottom_value ( & self , body : & Body < ' tcx > ) -> Self :: Domain {
51+ DenseBitSet :: new_empty ( body. local_decls . len ( ) )
52+ }
53+
54+ fn initialize_start_block ( & self , body : & Body < ' tcx > , state : & mut Self :: Domain ) {
55+ for arg in 1 ..=body. arg_count {
56+ state. insert ( Local :: from_usize ( arg) ) ;
57+ }
58+ }
59+
60+ fn apply_primary_statement_effect (
61+ & self ,
62+ state : & mut Self :: Domain ,
63+ stmt : & Statement < ' tcx > ,
64+ location : Location ,
65+ ) {
66+ TransferFunction { trans : state } . visit_statement ( stmt, location) ;
67+ }
68+
69+ fn apply_primary_terminator_effect < ' mir > (
70+ & self ,
71+ state : & mut Self :: Domain ,
72+ terminator : & ' mir Terminator < ' tcx > ,
73+ location : Location ,
74+ ) -> TerminatorEdges < ' mir , ' tcx > {
75+ TransferFunction { trans : state } . visit_terminator ( terminator, location) ;
76+ terminator. edges ( )
77+ }
78+ }
79+
1180impl < ' tcx > crate :: MirPass < ' tcx > for RemoveDeadDrops {
1281 fn is_required ( & self ) -> bool {
1382 true
1483 }
1584
1685 fn run_pass ( & self , tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
17- let move_data = MoveData :: gather_moves ( body, tcx, |_| true ) ;
18-
19- let mut maybe_init_cursor = MaybeInitializedPlaces :: new ( tcx, body, & move_data)
86+ let mut maybe_init_cursor = MaybeInitializedLocals
2087 . iterate_to_fixpoint ( tcx, body, None )
2188 . into_results_cursor ( body) ;
2289
@@ -26,18 +93,10 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveDeadDrops {
2693 if let Some ( terminator) = & data. terminator
2794 && let TerminatorKind :: Drop { place, target, .. } = & terminator. kind
2895 {
29- let LookupResult :: Exact ( path) = move_data. rev_lookup . find ( place. as_ref ( ) ) else {
30- continue ;
31- } ;
32-
3396 let term_location = Location { block, statement_index : data. statements . len ( ) } ;
3497 maybe_init_cursor. seek_before_primary_effect ( term_location) ;
3598
36- let is_dead = match maybe_init_cursor. get ( ) {
37- MaybeReachable :: Unreachable => true ,
38- MaybeReachable :: Reachable ( maybe_init) => !maybe_init. contains ( path) ,
39- } ;
40-
99+ let is_dead = !maybe_init_cursor. get ( ) . contains ( place. local ) ;
41100 if is_dead {
42101 dead_drops. push ( ( block, * target) ) ;
43102 }
0 commit comments