@@ -67,25 +67,24 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
6767 } ;
6868 let un_derefer = UnDerefer { tcx : tcx, derefer_sidetable : side_table } ;
6969 let elaborate_patch = {
70- let body = & * body;
7170 let env = MoveDataParamEnv { move_data, param_env } ;
72- let dead_unwinds = find_dead_unwinds ( tcx, body, & env, & un_derefer) ;
71+ remove_dead_unwinds ( tcx, body, & env, & un_derefer) ;
7372
7473 let inits = MaybeInitializedPlaces :: new ( tcx, body, & env)
7574 . into_engine ( tcx, body)
76- . dead_unwinds ( & dead_unwinds)
7775 . pass_name ( "elaborate_drops" )
7876 . iterate_to_fixpoint ( )
7977 . into_results_cursor ( body) ;
8078
8179 let uninits = MaybeUninitializedPlaces :: new ( tcx, body, & env)
8280 . mark_inactive_variants_as_uninit ( )
8381 . into_engine ( tcx, body)
84- . dead_unwinds ( & dead_unwinds)
8582 . pass_name ( "elaborate_drops" )
8683 . iterate_to_fixpoint ( )
8784 . into_results_cursor ( body) ;
8885
86+ let reachable = traversal:: reachable_as_bitset ( body) ;
87+
8988 ElaborateDropsCtxt {
9089 tcx,
9190 body,
@@ -94,6 +93,7 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
9493 drop_flags : Default :: default ( ) ,
9594 patch : MirPatch :: new ( body) ,
9695 un_derefer : un_derefer,
96+ reachable,
9797 }
9898 . elaborate ( )
9999 } ;
@@ -102,22 +102,21 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
102102 }
103103}
104104
105- /// Returns the set of basic blocks whose unwind edges are known
106- /// to not be reachable, because they are `drop` terminators
105+ /// Removes unwind edges which are known to be unreachable, because they are in `drop` terminators
107106/// that can't drop anything.
108- fn find_dead_unwinds < ' tcx > (
107+ fn remove_dead_unwinds < ' tcx > (
109108 tcx : TyCtxt < ' tcx > ,
110- body : & Body < ' tcx > ,
109+ body : & mut Body < ' tcx > ,
111110 env : & MoveDataParamEnv < ' tcx > ,
112111 und : & UnDerefer < ' tcx > ,
113- ) -> BitSet < BasicBlock > {
114- debug ! ( "find_dead_unwinds ({:?})" , body. span) ;
112+ ) {
113+ debug ! ( "remove_dead_unwinds ({:?})" , body. span) ;
115114 // We only need to do this pass once, because unwind edges can only
116115 // reach cleanup blocks, which can't have unwind edges themselves.
117- let mut dead_unwinds = BitSet :: new_empty ( body . basic_blocks . len ( ) ) ;
116+ let mut dead_unwinds = Vec :: new ( ) ;
118117 let mut flow_inits = MaybeInitializedPlaces :: new ( tcx, body, & env)
119118 . into_engine ( tcx, body)
120- . pass_name ( "find_dead_unwinds " )
119+ . pass_name ( "remove_dead_unwinds " )
121120 . iterate_to_fixpoint ( )
122121 . into_results_cursor ( body) ;
123122 for ( bb, bb_data) in body. basic_blocks . iter_enumerated ( ) {
@@ -129,16 +128,16 @@ fn find_dead_unwinds<'tcx>(
129128 _ => continue ,
130129 } ;
131130
132- debug ! ( "find_dead_unwinds @ {:?}: {:?}" , bb, bb_data) ;
131+ debug ! ( "remove_dead_unwinds @ {:?}: {:?}" , bb, bb_data) ;
133132
134133 let LookupResult :: Exact ( path) = env. move_data . rev_lookup . find ( place. as_ref ( ) ) else {
135- debug ! ( "find_dead_unwinds : has parent; skipping" ) ;
134+ debug ! ( "remove_dead_unwinds : has parent; skipping" ) ;
136135 continue ;
137136 } ;
138137
139138 flow_inits. seek_before_primary_effect ( body. terminator_loc ( bb) ) ;
140139 debug ! (
141- "find_dead_unwinds @ {:?}: path({:?})={:?}; init_data={:?}" ,
140+ "remove_dead_unwinds @ {:?}: path({:?})={:?}; init_data={:?}" ,
142141 bb,
143142 place,
144143 path,
@@ -150,13 +149,22 @@ fn find_dead_unwinds<'tcx>(
150149 maybe_live |= flow_inits. contains ( child) ;
151150 } ) ;
152151
153- debug ! ( "find_dead_unwinds @ {:?}: maybe_live={}" , bb, maybe_live) ;
152+ debug ! ( "remove_dead_unwinds @ {:?}: maybe_live={}" , bb, maybe_live) ;
154153 if !maybe_live {
155- dead_unwinds. insert ( bb) ;
154+ dead_unwinds. push ( bb) ;
156155 }
157156 }
158157
159- dead_unwinds
158+ if dead_unwinds. is_empty ( ) {
159+ return ;
160+ }
161+
162+ let basic_blocks = body. basic_blocks . as_mut ( ) ;
163+ for & bb in dead_unwinds. iter ( ) {
164+ if let Some ( unwind) = basic_blocks[ bb] . terminator_mut ( ) . unwind_mut ( ) {
165+ * unwind = None ;
166+ }
167+ }
160168}
161169
162170struct InitializationData < ' mir , ' tcx > {
@@ -290,6 +298,7 @@ struct ElaborateDropsCtxt<'a, 'tcx> {
290298 drop_flags : FxHashMap < MovePathIndex , Local > ,
291299 patch : MirPatch < ' tcx > ,
292300 un_derefer : UnDerefer < ' tcx > ,
301+ reachable : BitSet < BasicBlock > ,
293302}
294303
295304impl < ' b , ' tcx > ElaborateDropsCtxt < ' b , ' tcx > {
@@ -329,6 +338,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
329338
330339 fn collect_drop_flags ( & mut self ) {
331340 for ( bb, data) in self . body . basic_blocks . iter_enumerated ( ) {
341+ if !self . reachable . contains ( bb) {
342+ continue ;
343+ }
332344 let terminator = data. terminator ( ) ;
333345 let place = match terminator. kind {
334346 TerminatorKind :: Drop { ref place, .. }
@@ -384,6 +396,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
384396
385397 fn elaborate_drops ( & mut self ) {
386398 for ( bb, data) in self . body . basic_blocks . iter_enumerated ( ) {
399+ if !self . reachable . contains ( bb) {
400+ continue ;
401+ }
387402 let loc = Location { block : bb, statement_index : data. statements . len ( ) } ;
388403 let terminator = data. terminator ( ) ;
389404
@@ -541,6 +556,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
541556
542557 fn drop_flags_for_fn_rets ( & mut self ) {
543558 for ( bb, data) in self . body . basic_blocks . iter_enumerated ( ) {
559+ if !self . reachable . contains ( bb) {
560+ continue ;
561+ }
544562 if let TerminatorKind :: Call {
545563 destination, target : Some ( tgt) , cleanup : Some ( _) , ..
546564 } = data. terminator ( ) . kind
@@ -576,6 +594,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
576594 // clobbered before they are read.
577595
578596 for ( bb, data) in self . body . basic_blocks . iter_enumerated ( ) {
597+ if !self . reachable . contains ( bb) {
598+ continue ;
599+ }
579600 debug ! ( "drop_flags_for_locs({:?})" , data) ;
580601 for i in 0 ..( data. statements . len ( ) + 1 ) {
581602 debug ! ( "drop_flag_for_locs: stmt {}" , i) ;
0 commit comments