@@ -39,12 +39,12 @@ impl<'tcx> crate::MirPass<'tcx> for MoveElimination {
3939 let remapped_locals =
4040 PlaceUnification :: run ( tcx, body, & mut liveness_matrix, & mut unprojectable_locals) ;
4141
42- dump_liveness_matrix ( tcx, body, "MoveElimination.post-liveness" , & points , & liveness_matrix ) ;
42+ apply_mappings ( tcx, body, & remapped_locals ) ;
4343
44- let storage_to_rebuild = apply_mappings ( tcx, body, & remapped_locals ) ;
44+ dump_liveness_matrix ( tcx, body, "MoveElimination.post-liveness" , & points , & liveness_matrix ) ;
4545
4646 if tcx. sess . emit_lifetime_markers ( ) {
47- reconstruct_storage ( body, & points, & liveness_matrix, & storage_to_rebuild ) ;
47+ reconstruct_storage ( body, & points, & liveness_matrix) ;
4848 }
4949
5050 apply_alias_fixup ( tcx, body) ;
@@ -377,26 +377,14 @@ fn apply_mappings<'tcx>(
377377 tcx : TyCtxt < ' tcx > ,
378378 body : & mut Body < ' tcx > ,
379379 remapped_locals : & IndexVec < Local , Option < Place < ' tcx > > > ,
380- ) -> DenseBitSet < Local > {
381- let mut unified_locals = DenseBitSet :: new_empty ( body. local_decls . len ( ) ) ;
382- for ( src, dst) in remapped_locals. iter_enumerated ( ) {
383- if let Some ( dst_place) = dst {
384- unified_locals. insert ( src) ;
385- unified_locals. insert ( dst_place. local ) ;
386- }
387- }
388-
389- let storage_to_rebuild = DenseBitSet :: new_empty ( body. local_decls . len ( ) ) ;
390- let mut rewriter = PlaceUpdater { tcx, remapped_locals, unified_locals, storage_to_rebuild } ;
380+ ) {
381+ let mut rewriter = PlaceUpdater { tcx, remapped_locals } ;
391382 rewriter. visit_body_preserves_cfg ( body) ;
392- rewriter. storage_to_rebuild
393383}
394384
395385struct PlaceUpdater < ' a , ' tcx > {
396386 tcx : TyCtxt < ' tcx > ,
397387 remapped_locals : & ' a IndexVec < Local , Option < Place < ' tcx > > > ,
398- unified_locals : DenseBitSet < Local > ,
399- storage_to_rebuild : DenseBitSet < Local > ,
400388}
401389
402390impl < ' tcx > MutVisitor < ' tcx > for PlaceUpdater < ' _ , ' tcx > {
@@ -425,17 +413,11 @@ impl<'tcx> MutVisitor<'tcx> for PlaceUpdater<'_, 'tcx> {
425413
426414 fn visit_statement ( & mut self , statement : & mut Statement < ' tcx > , location : Location ) {
427415 match statement. kind {
428- StatementKind :: StorageDead ( local) | StatementKind :: StorageLive ( local)
429- if self . unified_locals . contains ( local) =>
430- {
431- // Only rebuild storage for locals that previously had storage
432- // statements.
433- let mapped_local = match self . remapped_locals [ local] {
434- Some ( place) => place. local ,
435- None => local,
436- } ;
437- self . storage_to_rebuild . insert ( mapped_local) ;
438-
416+ // Remove *all* storage statements. These are rebuilt from liveness
417+ // information later. Also, since we've preserved StorageDead in
418+ // unwind paths until now, we will want to remove those since they
419+ // hurt LLVM's codegen.
420+ StatementKind :: StorageDead ( _) | StatementKind :: StorageLive ( _) => {
439421 statement. make_nop ( true ) ;
440422 return ;
441423 }
@@ -476,21 +458,21 @@ fn get_or_split_edge<'tcx>(
476458 split_bb
477459}
478460
461+ /// Don't insert storage statements in cleanup blocks and in unreachable blocks.
462+ fn should_insert_storage < ' tcx > ( block_data : & BasicBlockData < ' tcx > ) -> bool {
463+ !block_data. is_cleanup && !matches ! ( block_data. terminator( ) . kind, TerminatorKind :: Unreachable )
464+ }
465+
479466/// Re-constructs storage statements for all locals.
480467fn reconstruct_storage < ' tcx > (
481468 body : & mut Body < ' tcx > ,
482469 points : & DenseLocationMap ,
483470 liveness_matrix : & SparseIntervalMatrix < Local , SplitPointIndex > ,
484- storage_to_rebuild : & DenseBitSet < Local > ,
485471) {
486472 let mut patcher = MirPatch :: new ( body) ;
487473 let mut split_edges: FxHashMap < ( BasicBlock , BasicBlock ) , BasicBlock > = Default :: default ( ) ;
488474
489475 for local in body. local_decls . indices ( ) {
490- if !storage_to_rebuild. contains ( local) {
491- continue ;
492- }
493-
494476 // Arguments and return values don't use storage statements.
495477 match body. local_kind ( local) {
496478 LocalKind :: Arg | LocalKind :: ReturnPointer => continue ,
@@ -543,9 +525,8 @@ fn reconstruct_storage<'tcx>(
543525 local : Local ,
544526 block : BasicBlock | {
545527 for succ in body. basic_blocks [ block] . terminator ( ) . successors ( ) {
546- // Don't emit StorageDead in cleanup blocks.
547- if body. basic_blocks [ succ] . is_cleanup {
548- continue ;
528+ if !should_insert_storage ( & body. basic_blocks [ succ] ) {
529+ return ;
549530 }
550531
551532 if !row. contains ( SplitPointIndex :: new (
@@ -576,19 +557,24 @@ fn reconstruct_storage<'tcx>(
576557 // If the live range starts at the `Early` point then it means that
577558 // the value came from a predecessor block. A write from the first
578559 // statement would happen at the `Late` point instead.
579- if range. start
580- == SplitPointIndex :: new ( points. entry_point ( start_block) , SplitPointEffect :: Early )
581- {
582- // If the local is dead at the end of any predecessor block then
583- // emit a `StorageLive` before the terminator.
584- emit_storage_live_in_preds ( body, & mut patcher, local, start_block) ;
585- } else {
586- // Otherwise just add `StorageLive` before the statement that
587- // starts the live range.
588- patcher. add_statement (
589- points. to_location ( range. start . point ( ) ) ,
590- StatementKind :: StorageLive ( local) ,
591- ) ;
560+ if should_insert_storage ( & body. basic_blocks [ start_block] ) {
561+ if range. start
562+ == SplitPointIndex :: new (
563+ points. entry_point ( start_block) ,
564+ SplitPointEffect :: Early ,
565+ )
566+ {
567+ // If the local is dead at the end of any predecessor block then
568+ // emit a `StorageLive` before the terminator.
569+ emit_storage_live_in_preds ( body, & mut patcher, local, start_block) ;
570+ } else {
571+ // Otherwise just add `StorageLive` before the statement that
572+ // starts the live range.
573+ patcher. add_statement (
574+ points. to_location ( range. start . point ( ) ) ,
575+ StatementKind :: StorageLive ( local) ,
576+ ) ;
577+ }
592578 }
593579
594580 // The live range may span multiple blocks because
@@ -598,24 +584,30 @@ fn reconstruct_storage<'tcx>(
598584 let mut current_block = start_block;
599585 debug_assert ! ( start_block <= end_block) ;
600586 while current_block != end_block {
601- emit_storage_dead_in_succs ( body, & mut patcher, local, current_block) ;
587+ if should_insert_storage ( & body. basic_blocks [ current_block] ) {
588+ emit_storage_dead_in_succs ( body, & mut patcher, local, current_block) ;
589+ }
602590 current_block = BasicBlock :: from_usize ( current_block. index ( ) + 1 ) ;
603- emit_storage_live_in_preds ( body, & mut patcher, local, current_block) ;
591+ if should_insert_storage ( & body. basic_blocks [ current_block] ) {
592+ emit_storage_live_in_preds ( body, & mut patcher, local, current_block) ;
593+ }
604594 }
605595
606596 // We need to insert `StorageDead` after the last statement that
607597 // uses a local. If this is a terminator then we need to instead
608598 // insert it at the start of every successor block where the local
609599 // is dead on entry.
610- if range. last . point ( ) == points. terminator ( end_block) {
611- emit_storage_dead_in_succs ( body, & mut patcher, local, current_block) ;
612- } else {
613- // Don't emit StorageDead in cleanup blocks.
614- if !body. basic_blocks [ end_block] . is_cleanup {
615- patcher. add_statement (
616- points. to_location ( range. last . point ( ) ) . successor_within_block ( ) ,
617- StatementKind :: StorageDead ( local) ,
618- ) ;
600+ if should_insert_storage ( & body. basic_blocks [ end_block] ) {
601+ if range. last . point ( ) == points. terminator ( end_block) {
602+ emit_storage_dead_in_succs ( body, & mut patcher, local, current_block) ;
603+ } else {
604+ // Don't emit StorageDead in cleanup blocks.
605+ if !body. basic_blocks [ end_block] . is_cleanup {
606+ patcher. add_statement (
607+ points. to_location ( range. last . point ( ) ) . successor_within_block ( ) ,
608+ StatementKind :: StorageDead ( local) ,
609+ ) ;
610+ }
619611 }
620612 }
621613 }
0 commit comments