@@ -30,6 +30,8 @@ impl<'tcx> crate::MirPass<'tcx> for CopyProp {
3030
3131 let typing_env = body. typing_env ( tcx) ;
3232 let ssa = SsaLocals :: new ( tcx, body, typing_env) ;
33+ debug ! ( borrowed_locals = ?ssa. borrowed_locals( ) ) ;
34+ debug ! ( copy_classes = ?ssa. copy_classes( ) ) ;
3335
3436 let fully_moved = fully_moved_locals ( & ssa, body) ;
3537 debug ! ( ?fully_moved) ;
@@ -43,14 +45,8 @@ impl<'tcx> crate::MirPass<'tcx> for CopyProp {
4345
4446 let any_replacement = ssa. copy_classes ( ) . iter_enumerated ( ) . any ( |( l, & h) | l != h) ;
4547
46- Replacer {
47- tcx,
48- copy_classes : ssa. copy_classes ( ) ,
49- fully_moved,
50- borrowed_locals : ssa. borrowed_locals ( ) ,
51- storage_to_remove,
52- }
53- . visit_body_preserves_cfg ( body) ;
48+ Replacer { tcx, copy_classes : ssa. copy_classes ( ) , fully_moved, storage_to_remove }
49+ . visit_body_preserves_cfg ( body) ;
5450
5551 if any_replacement {
5652 crate :: simplify:: remove_unused_definitions ( body) ;
@@ -102,7 +98,6 @@ struct Replacer<'a, 'tcx> {
10298 tcx : TyCtxt < ' tcx > ,
10399 fully_moved : DenseBitSet < Local > ,
104100 storage_to_remove : DenseBitSet < Local > ,
105- borrowed_locals : & ' a DenseBitSet < Local > ,
106101 copy_classes : & ' a IndexSlice < Local , Local > ,
107102}
108103
@@ -111,34 +106,27 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
111106 self . tcx
112107 }
113108
109+ #[ tracing:: instrument( level = "trace" , skip( self ) ) ]
114110 fn visit_local ( & mut self , local : & mut Local , ctxt : PlaceContext , _: Location ) {
115111 let new_local = self . copy_classes [ * local] ;
116- // We must not unify two locals that are borrowed. But this is fine if one is borrowed and
117- // the other is not. We chose to check the original local, and not the target. That way, if
118- // the original local is borrowed and the target is not, we do not pessimize the whole class.
119- if self . borrowed_locals . contains ( * local) {
120- return ;
121- }
122112 match ctxt {
123113 // Do not modify the local in storage statements.
124114 PlaceContext :: NonUse ( NonUseContext :: StorageLive | NonUseContext :: StorageDead ) => { }
125- // The local should have been marked as non-SSA.
126- PlaceContext :: MutatingUse ( _) => assert_eq ! ( * local, new_local) ,
127115 // We access the value.
128116 _ => * local = new_local,
129117 }
130118 }
131119
132- fn visit_place ( & mut self , place : & mut Place < ' tcx > , _: PlaceContext , loc : Location ) {
120+ #[ tracing:: instrument( level = "trace" , skip( self ) ) ]
121+ fn visit_place ( & mut self , place : & mut Place < ' tcx > , ctxt : PlaceContext , loc : Location ) {
133122 if let Some ( new_projection) = self . process_projection ( place. projection , loc) {
134123 place. projection = self . tcx ( ) . mk_place_elems ( & new_projection) ;
135124 }
136125
137- // Any non-mutating use context is ok.
138- let ctxt = PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Copy ) ;
139126 self . visit_local ( & mut place. local , ctxt, loc)
140127 }
141128
129+ #[ tracing:: instrument( level = "trace" , skip( self ) ) ]
142130 fn visit_operand ( & mut self , operand : & mut Operand < ' tcx > , loc : Location ) {
143131 if let Operand :: Move ( place) = * operand
144132 // A move out of a projection of a copy is equivalent to a copy of the original
@@ -151,6 +139,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
151139 self . super_operand ( operand, loc) ;
152140 }
153141
142+ #[ tracing:: instrument( level = "trace" , skip( self ) ) ]
154143 fn visit_statement ( & mut self , stmt : & mut Statement < ' tcx > , loc : Location ) {
155144 // When removing storage statements, we need to remove both (#107511).
156145 if let StatementKind :: StorageLive ( l) | StatementKind :: StorageDead ( l) = stmt. kind
0 commit comments